using Assets.Scripts.UI.Control; using DG.Tweening; using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.UI; namespace Assets.Scripts { public static class Utils { /*获取ip*/ public enum ADDRESSFAM { IPv4, IPv6 } /// /// 获取本机IP /// /// 要获取的IP类型 /// public static string GetIP(ADDRESSFAM Addfam) { if (Addfam == ADDRESSFAM.IPv6 && !Socket.OSSupportsIPv6) { return null; } string output = ""; foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN NetworkInterfaceType _type1 = NetworkInterfaceType.Wireless80211; NetworkInterfaceType _type2 = NetworkInterfaceType.Ethernet; if ((item.NetworkInterfaceType == _type1 || item.NetworkInterfaceType == _type2) && item.OperationalStatus == OperationalStatus.Up) #endif { foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses) { //IPv4 if (Addfam == ADDRESSFAM.IPv4) { if (ip.Address.AddressFamily == AddressFamily.InterNetwork) { output = ip.Address.ToString(); //Debug.Log("IP:" + output); } } //IPv6 else if (Addfam == ADDRESSFAM.IPv6) { if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6) { output = ip.Address.ToString(); } } } } } return output; } /// /// /// /// /// 直接输入面板坐标即可 /// public static Vector3 GetTruePosition(this Transform rect, Vector2 point) { if (!rect.parent) return point; RectTransform myRect = rect.GetComponent() ,prect = rect.parent.GetComponent(); return new Vector2(point.x + prect.sizeDelta.x * (myRect.pivot.x - prect.pivot.x), point.y + prect.sizeDelta.y * (myRect.pivot.y - prect.pivot.y)); } public static bool isPointInTransfrom(this RectTransform rect,Vector2 point) { var MainCanvas = UIManager.Instance.MainCanvas; if (!MainCanvas) return false; var size = rect.sizeDelta * MainCanvas.transform.localScale; var sPoint = new Vector2(rect.position.x - rect.pivot.x * size.x, rect.position.y - rect.pivot.y * size.y); var ePoint = new Vector2(rect.position.x + (1 - rect.pivot.x) * size.x, rect.position.y + (1 - rect.pivot.y) * size.y); return point.x >= sPoint.x && point.x <= ePoint.x && point.y >= sPoint.y && point.y <= ePoint.y; } public static bool isLowIPhone() { var info = SystemInfo.deviceModel; if (info.Contains("iPhone")) { //iPhone2,1 var s = info.Replace("iPhone", "").Split(','); return s.Length == 2 && int.TryParse(s[0],out int gen) && gen < 9; } return false; } /*获取ip*/ /*显示简略提示,需要拖Toast的预制件,且保证其他组件名字不是Toast,ToastContainer*/ private static Dictionary _toastDict; private static Dictionary toastDict { get { if (_toastDict == null) { _toastDict = new Dictionary { {0,"Images/home/wrong|#f93086" },{1,"Images/home/right|#41A6FE" } }; } return _toastDict; } set { _toastDict = value; } } private static Dictionary _deviceDict; public static Dictionary deviceDict { get { if (_deviceDict == null) { _deviceDict = new Dictionary { {"Trainer","Smart Trainer|Images/Devices/Trainer_3" }, {"Power","Power Meter|Images/Devices/Power_3" }, {"Cadence","Cadence Sensor|Images/Devices/Cadence_3" }, {"HeartRate","Heart Rate Monitor|Images/Devices/Heart Rate_3" }, {"SpeedCadence","Cadence Sensor|Images/Devices/Cadence_3" }, {"Speed","Speed Meter|Images/Devices/Speed_3" }, {"Rower","Rower Machine|Images/Rower/设备 - 划船机" } }; } return _deviceDict; } private set { _deviceDict = value; } } /// /// /// /// /// /// /// 0 错误 1 正确 /// /// /// /// /// public static void showToast(GameObject p, string text, int duration = 2, int type = 0, Func stopFunc = null, bool isLowest = false,bool showSeconds = false,Action endCallback = null,PFUIPanel _parent = null) { var parent = UIManager.Instance.ModalsPanel; if (parent == null) { if (_parent) { parent = _parent; } else { return; } } if (!parent.gameObject.activeInHierarchy) parent.gameObject.SetActive(true); var toast = parent.transform.Find("ToastContainer"); if (toast != null) { MonoBehaviour.DestroyImmediate(toast.gameObject); } #if UNITY_IOS || UNITY_ANDROID var newToast = MonoBehaviour.Instantiate(Resources.Load("UI/Prefab/ToastContainer-mobile")); #else var newToast = MonoBehaviour.Instantiate(Resources.Load("UI/Prefab/ToastContainer")); #endif newToast.name = "ToastContainer"; newToast.GetComponent().position = new Vector3(Screen.width / 2, Screen.height / 2, 0); newToast.transform.parent = parent.transform; toast = newToast.transform; var toastStyle = toastDict[type].Split('|'); if (isLowest) { toast.SetAsFirstSibling(); } else { toast.SetAsLastSibling(); } toast.Find("Image").GetComponent().sprite = Resources.Load(toastStyle[0]); toast.GetComponent().color = HexToColorHtml(toastStyle[1]); toast.GetComponent().showToast(new ToastParams { text = text, duration = duration, func = stopFunc, showSeconds = showSeconds, endCallback = endCallback }); } public class ToastParams { public bool showSeconds { get; set; } public string text { get; set; } public int duration { get; set; } public Func func { get; set; } public Action endCallback { get; set; } } /*显示简略提示,需要拖Toast的预制件,且保证其他组件名字不是Toast,ToastContainer*/ public static void showLoading(this GameObject game) { var parent = Utils.FindUpParent(game.transform); var loading = parent.Find("Loading"); if (loading == null) { #if UNITY_IOS || UNITY_ANDROID var newLoading = MonoBehaviour.Instantiate(Resources.Load("UI/Prefab/Common/Mobile/Loading")); #else var newLoading = MonoBehaviour.Instantiate(Resources.Load("UI/Prefab/Common/Loading")); #endif newLoading.name = "Loading"; newLoading.GetComponent().position = new Vector3(Screen.width / 2, Screen.height / 2, 0); newLoading.transform.parent = parent; loading = newLoading.transform; } loading.GetComponent().Show(); } public static bool isUpdate(string currentVersion,string realVersion) { var a = currentVersion.Split('.'); var b = realVersion.Split('.'); if (a.Length != 3 || b.Length != 3) return false; for (int i = 0; i < 3; i++) { var f1 = int.TryParse(a[i], out int ai); var f2 = int.TryParse(b[i], out int bi); if (!f1 || !f2) return false; if (ai < bi) { return true; } else if (ai > bi) { return false; } } return false; } public static void CallAndroidMethod(string methodName,params object[] args) { #if UNITY_ANDROID && !UNITY_EDITOR AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); var activity = jc.GetStatic("currentActivity"); activity.Call(methodName, args); #endif } public static void showLoadingExtension(this GameObject game) { game.SetActive(true); var loading = game.transform.Find("Loading"); if (loading == null) { #if UNITY_IOS || UNITY_ANDROID var newLoading = MonoBehaviour.Instantiate(Resources.Load("UI/Prefab/Common/Mobile/Loading")); #else var newLoading = MonoBehaviour.Instantiate(Resources.Load("UI/Prefab/Common/Loading")); #endif newLoading.name = "Loading"; newLoading.GetComponent().position = new Vector3(Screen.width / 2, Screen.height / 2, 0); newLoading.transform.SetParent(game.transform); loading = newLoading.transform; loading.localScale = new Vector3(1, 1, 1); } loading.GetComponent().Show(); } public static void hideLoadingExtension(this GameObject game) { var loading = game.transform.Find("Loading"); if (loading != null) { loading.GetComponent().Close(); } game.SetActive(false); } public static void hideLoading(this GameObject game) { var parent = Utils.FindUpParent(game.transform); var loading = parent.Find("Loading"); if (loading != null) { //loading.gameObject.SetActive(false); loading.GetComponent().Close(); } } /*删除父亲节点下的所有孩子*/ static public void DestroyChildren(this Transform t,string igNoreName = null) { bool isPlaying = Application.isPlaying; while (t.childCount != 0) { Transform child = t.GetChild(0); if (isPlaying) { child.SetParent(null); UnityEngine.Object.Destroy(child.gameObject); } else UnityEngine.Object.DestroyImmediate(child.gameObject); } Resources.UnloadUnusedAssets(); GC.Collect(); } /*删除父亲节点下的所有孩子*/ /*显示网络图片*/ public static void GetImageBytes(string url, Action p) { if (string.IsNullOrEmpty(url)) return; UIManager.Instance.StartCoroutine(DownloadImageByte(url, p)); } public static Dictionary propTextureCache = new Dictionary(); public delegate Coroutine StartCoroutine(IEnumerator routine); public static void DisplayImage(MaskableGraphic img, string url, bool cache = false,Dictionary caches = null) { if (string.IsNullOrEmpty(url)) return; //可以考虑缓存到硬盘里 //Texture2D tex = null; //byte[] fileData; // //if (File.Exists(filePath)) //{ // fileData = File.ReadAllBytes(filePath); // tex = new Texture2D(2, 2); // tex.LoadImage(fileData); //..this will auto-resize the texture dimensions. //} if (cache) { if (propTextureCache.ContainsKey(url)) { var texture = propTextureCache[url]; if (img.GetComponent()) { img.GetComponent().texture = texture; } else if (img.GetComponent()) { img.GetComponent().ShowImageWithTexture(texture); } return; } } UIManager.Instance.StartCoroutine(DownloadImage(img, url,(texture)=> { if (cache && !propTextureCache.ContainsKey(url)) { propTextureCache.Add(url, texture); } })); } /// /// 使用临时字典存放图片,切换页面后清除 /// /// /// /// public static void DisplayImageTempDict(MaskableGraphic img, string url, Dictionary caches = null,UnityAction callback = null) { if (string.IsNullOrEmpty(url)) return; if (caches!=null) { if (caches.ContainsKey(url)) { var texture = caches[url]; if (img.GetComponent()) { img.GetComponent().texture = texture; } else if (img.GetComponent()) { img.GetComponent().ShowImageWithTexture(texture); } if (callback != null) { callback.Invoke(null); } return; } } UIManager.Instance.StartCoroutine(DownloadImage(img, url, (texture) => { if (caches != null && !caches.ContainsKey(url)) { caches.Add(url, texture); } },callback)); } public static void DisplayImageAysnc(StartCoroutine startCoroutine, RawImage img, string url,Action action) { startCoroutine(DownloadImageCallBack(img, url, action)); } static IEnumerator DownloadImageByte(string MediaUrl, Action action = null) { UnityWebRequest request = UnityWebRequest.Get(MediaUrl); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.Log(request.error); action.Invoke(null); } else { if (action != null) { action.Invoke(request.downloadHandler.data); } } } static IEnumerator DownloadImage(MaskableGraphic img,string MediaUrl, Action action = null,UnityAction callback = null) { UnityWebRequest request = UnityWebRequest.Get(MediaUrl); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) Debug.Log(request.error); else if (img != null) { var data = request.downloadHandler.data; var texture = Utils.GetDownloadTexture(MediaUrl, data); if (img.GetComponent()) { img.GetComponent().texture = texture; } else if(img.GetComponent()) { img.GetComponent().ShowImageWithTexture(texture); } if (action != null) { action.Invoke(texture); } if (callback != null) { callback.Invoke(data); } } } public static Texture GetDownloadTexture(string MediaUrl, byte[] data) { #if UNITY_EDITOR var _t = new Texture2D(4, 4, TextureFormat.DXT5, false); #else #if UNITY_IOS var _t = new Texture2D(4, 4, TextureFormat.ASTC_RGB_4x4,false); Debug.Log("使用了壓縮"); #elif UNITY_ANDROID var _t = new Texture2D(4, 4, TextureFormat.ASTC_RGB_4x4,false); Debug.Log("使用了壓縮"); #else //pc var _t = new Texture2D(4, 4, TextureFormat.DXT5,false); #endif #endif _t.LoadImage(data,true); _t.name = MediaUrl; return _t; } static IEnumerator DownloadImageCallBack(RawImage img, string MediaUrl,Action action) { UnityWebRequest request = UnityWebRequest.Get(MediaUrl); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) Debug.Log(request.error); else { var data = request.downloadHandler.data; img.texture = Utils.GetDownloadTexture(MediaUrl, data); action.Invoke(MediaUrl, img); } } /*显示网络图片*/ /*获取最顶层对象*/ public static Transform FindUpParent(Transform zi) { if (zi.parent == null) return zi; else return FindUpParent(zi.parent); } /*获取最顶层对象*/ /*Texture相关*/ public static Texture2D DeCompress(this Texture2D source) { RenderTexture renderTex = RenderTexture.GetTemporary( source.width, source.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear); Graphics.Blit(source, renderTex); RenderTexture previous = RenderTexture.active; RenderTexture.active = renderTex; Texture2D readableText = new Texture2D(source.width, source.height); readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0); readableText.Apply(); RenderTexture.active = previous; RenderTexture.ReleaseTemporary(renderTex); return readableText; } public static void WriteTextureToPlayerPrefs(string tag, Texture2D tex) { // if texture is png otherwise you can use tex.EncodeToJPG(). byte[] texByte = tex.DeCompress().EncodeToJPG(); // convert byte array to base64 string string base64Tex = System.Convert.ToBase64String(texByte); // write string to playerpref PlayerPrefs.SetString(tag, base64Tex); PlayerPrefs.Save(); } public static Texture2D ReadTextureFromPlayerPrefs(string tag) { // load string from playerpref string base64Tex = PlayerPrefs.GetString(tag, null); if (!string.IsNullOrEmpty(base64Tex)) { // convert it to byte array byte[] texByte = System.Convert.FromBase64String(base64Tex); #if UNITY_ANDROID || UNITY_IOS Texture2D tex = new Texture2D(4, 4, TextureFormat.ASTC_RGB_4x4,false); #else Texture2D tex = new Texture2D(4, 4, TextureFormat.DXT5,false); #endif //load texture from byte array if (tex.LoadImage(texByte)) { return tex; } } return null; } /*Texture相关*/ public static byte[] StreamToBytes(Stream stream) { byte[] bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); // 设置当前流的位置为流的开始 stream.Seek(0, SeekOrigin.Begin); return bytes; } public static Color HexToColor(string hex) { byte r = byte.Parse(hex.Substring(0, 2), NumberStyles.HexNumber); byte g = byte.Parse(hex.Substring(2, 2), NumberStyles.HexNumber); byte b = byte.Parse(hex.Substring(4, 2), NumberStyles.HexNumber); return new Color32(r, g, b, byte.MaxValue); } public static Color HexToColorHtml(string hex) { ColorUtility.TryParseHtmlString(hex, out Color c); return c; } /// /// Generate random digit code /// /// Length /// Result string public static string GenerateRandomDigitCode(int length) { var random = new System.Random(); string str = string.Empty; for (int i = 0; i < length; i++) str = String.Concat(str, random.Next(10).ToString()); return str; } /*文件转精灵*/ public static Sprite PngToSprite(string fullPath, int x, int y) { using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read)) //自动双清 { fs.Seek(0, SeekOrigin.Begin); //设定当前流的位置 byte[] bytes = new byte[fs.Length]; //创建文件长度缓冲区 fs.Read(bytes, 0, (int)fs.Length); //读取文件 Texture2D texture = new Texture2D(x, y); //创建Texture texture.LoadImage(bytes); return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.one / 2); } } /*文件转精灵*/ /*打开文件*/ public delegate void OpenFileCallBack(string path); public static void OpenFile(OpenFileCallBack callBack,string filter = null) { OpenFileName ofn = new OpenFileName(); ofn.structSize = Marshal.SizeOf(ofn); ofn.filter = "Image Files(*.jpg;*.jpeg;*.png;*.bmp)\0*.jpg;*.png;*.jpeg;*.bmp\0"; if (filter != null) ofn.filter = filter; ofn.file = new string(new char[256]); ofn.maxFile = ofn.file.Length; ofn.fileTitle = new string(new char[64]); ofn.maxFileTitle = ofn.fileTitle.Length; ofn.initialDir = UnityEngine.Application.dataPath;//默认路径 ofn.title = "Open Project"; ofn.defExt = "JPG";//显示文件的类型 //注意 一下项目不一定要全选 但是0x00000008项不要缺少 ofn.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008; //0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008 OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST| OFN_ALLOWMULTISELECT|OFN_NOCHANGEDIR if (Win32.GetOpenFileName(ofn)) { callBack(ofn.file); } } /*打开文件*/ /*文本框/下拉框错误*/ public static void SetValidate(Dictionary dict, JArray errorList) { if (errorList == null) return; foreach (var error in errorList) { var className = dict[error.Value("Field")].GetType().Name; if (className == "InputField") { dict[error.Value("Field")].GetComponent() .SetValidate(true); } else if (className == "Dropdown") { dict[error.Value("Field")].GetComponent() .SetValidate(); } //formDict[error.Value("Filed")].error.Value("ErrMsg"); } } /*文本框/下拉框错误*/ public static void ExecFile(string path,string args = "") { System.Diagnostics.Process proc = null; try { proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = path; proc.StartInfo.Arguments = args; proc.StartInfo.CreateNoWindow = false; proc.StartInfo.Verb = "runas"; proc.Start(); } catch (Exception ex) { Console.WriteLine("执行批处理的时候出现了异常!"); } } /*下载文件*/ public static void DisplayHead(MaskableGraphic raw, string s) { if (string.IsNullOrEmpty(s)) { var t = Resources.Load("Images/icon-1024"); if (raw.GetComponent()) { raw.GetComponent().texture = Resources.Load("Images/icon-1024"); } else if (raw.GetComponent()) { raw.GetComponent().ShowImageWithTexture(t); } } else { DisplayImage(raw, s); } } public static void ShowImageWithTexture(this Image img, Texture t) { img.sprite = Sprite.Create((Texture2D)t, new Rect(0, 0, t.width, t.height), Vector2.zero); } public static void SetTextWithEllipsis(this Text textComponent, string value) { var generator = new TextGenerator(); var rectTransform = textComponent.GetComponent(); var settings = textComponent.GetGenerationSettings(rectTransform.rect.size); generator.Populate(value, settings); var characterCountVisible = generator.characterCountVisible; var updatedText = value; if (value.Length > characterCountVisible && characterCountVisible != -1) { updatedText = value.Substring(0, characterCountVisible - 3); updatedText += "…"; } textComponent.text = updatedText; } public static string GetCountDown(TimeSpan time) { var second = Math.Ceiling(time.TotalSeconds); var ts = TimeSpan.FromSeconds(second); return $"{ (int)ts.TotalHours }:{ts:mm}:{ts:ss}"; } private static IEnumerator TimerFunc(float seconds, Action action) { while (true) { yield return new WaitForSeconds(seconds); // 停止执行1秒 action.Invoke(); //time = UIManager.Now.GetDateTime().AddSeconds(1); } } public static void StartTimeUnLimit(float seconds,Action action) { UIManager.Instance.StartCoroutine(TimerFunc(seconds, action)); } public static void MyDOFade(this Transform transform) { var cg = transform.GetComponent(); if (cg) { cg.alpha = 0; #if UNITY_IOS cg.DOFade(1f, .6f); #else cg.DOFade(1f, .3f); #endif } } public static IEnumerator StartLocation(Action action = null) { // Check if the user has location service enabled. if (!Input.location.isEnabledByUser) yield break; // Starts the location service. Input.location.Start(); // Waits until the location service initializes int maxWait = 20; while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0) { yield return new WaitForSeconds(1); maxWait--; } // If the service didn't initialize in 20 seconds this cancels location service use. if (maxWait < 1) { Debug.Log("Timed out"); yield break; } // If the connection failed this cancels location service use. if (Input.location.status == LocationServiceStatus.Failed) { Debug.Log("Unable to determine device location"); yield break; } else { // If the connection succeeded, this retrieves the device's current location and displays it in the Console window. Debug.Log("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp); if (action != null) { action.Invoke(Input.location.lastData); } } // Stops the location service if there is no need to query location updates continuously. Input.location.Stop(); } public static string ToLocalString(this DateTime time, string format) { if (App.GetLocalLanguage() == "en") { return time.ToString(format); } else { if(format == "HH:mm:ss dd-MM-yyyy") return time.ToString("yyyy-MM-dd HH:mm:ss"); else return time.ToString("yyyy-MM-dd"); } } } }