using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using System.Linq; using System.Reflection; using System.IO; using System.Runtime.CompilerServices; using UnityEngine.Networking; using System; using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Linq; using System.Text; using System.IO.Compression; using System.Data; using UnityEngine.UIElements; namespace BITKit { public static partial class MathQ { public static bool IsNaN(this Quaternion self) { return float.IsNaN(self.x) || float.IsNaN(self.y) || float.IsNaN(self.z) || float.IsNaN(self.w); } } public static partial class MathV { public static bool IsNaN(this Vector3 self) { return float.IsNaN(self.x) || float.IsNaN(self.y) || float.IsNaN(self.z); } public static Vector2 Fix(this Vector2 self, int length = 1024) { if (MathB.IsNormal(self.x, length) is false) { self.x = 0; } if (MathB.IsNormal(self.y, length) is false) { self.y = 0; } return self; } public static Vector3 Fix(this Vector3 self, int length = 1024) { if (MathB.IsNormal(self.x, length) is false) { self.x = 0; } if (MathB.IsNormal(self.y, length) is false) { self.y = 0; } if (MathB.IsNormal(self.z, length) is false) { self.z = 0; } return self; } public static bool Parallel(Vector2 vectorX, Vector2 vectorY) { return (vectorX, vectorY) switch { var (x, y) when (x.x > 0 && y.x > 0 && x.y > 0 && y.y > 0) => true, var (x, y) when (x.x < 0 && y.x < 0 && x.y < 0 && y.y < 0) => true, _ => false, }; } public static bool Approximately(Vector2 vectorX, Vector2 vectorY, float factor = 8) { /* var direction = vectorX - vectorY; return direction.sqrMagnitude < factor; */ return Vector3.Angle(vectorX, vectorY) < 8; } public static Vector3 TransientRotationAxis(Vector3 transientAxis) { transientAxis.x = TransientRotationAxis(transientAxis.x); transientAxis.y = TransientRotationAxis(transientAxis.y); transientAxis.z = TransientRotationAxis(transientAxis.z); return transientAxis; } public static Vector3Int Align(this Vector3 self, int snapSize = 64) { Vector3Int result = new() { x = GetAlign(self.x), y = GetAlign(self.y), z = GetAlign(self.z), }; return result * snapSize; int GetAlign(float _self) { var size = (int)_self / snapSize; var remainder = _self % snapSize; return remainder > snapSize / 2 ? size + 1 : size; } } public static float GetLength(this Vector3 self) { return Mathf.Max(Mathf.Abs(self.x), Mathf.Abs(self.y), Mathf.Abs(self.z)); } public static float GetValue(this Vector3 self) { var addValue = self.x + self.y + self.z; var subtractValue = self.x - self.y - self.z; if (Math.Abs(MathF.Abs(addValue) - Mathf.Abs(subtractValue)) < 0.01f) { return addValue; } else { var sb = new StringBuilder(); sb.AppendLine("Not a valid vector"); sb.AppendLine($"{self.x}+{self.y}+{self.z} = {addValue}"); sb.AppendLine($"{self.x}-{self.y}-{self.z} = {subtractValue}"); sb.AppendLine($"{addValue}"); sb.AppendLine($"{subtractValue}"); throw new Exception(sb.ToString()); } } public static bool InRange(this Vector2Int self, Vector2Int other) { return self.x >= 0 && self.y >= 0 && other.x >= 0 && other.y >= 0 && other.x <= self.x && other.y <= self.y && (self + other).x >= 0 && (self + other).y >= 0; } public static float TransientRotationAxis(this float transientAxis) { return (transientAxis %= 360) switch { var x when x > 180 => transientAxis - 360, var x when x < -180 => transientAxis + 360, _ => transientAxis, }; } public static float WrapAngle(float angle) { angle %= 360; if (angle > 180) return angle - 360; return angle; } public static Vector3 WrapAngle(Vector3 vector) { return new Vector3 { x = WrapAngle(vector.x), y = WrapAngle(vector.y), z = WrapAngle(vector.z), }; } private static float UnwrapAngle(float angle) { if (angle >= 0) return angle; angle = -angle % 360; return 360 - angle; } public static Vector2Int ToVector2Int(this Vector2 self) { return new Vector2Int { x = (int)self.x, y = (int)self.y, }; } } public static partial class Utility { public static bool Includes(this LayerMask mask, int layer) { return (mask.value & 1 << layer) > 0; } public static byte[] ToByte(this string self) { return System.Text.Encoding.UTF8.GetBytes(self); } public static string Padding(this string self, int length = 16, char c = ' ') { Encoding coding = Encoding.GetEncoding("gb2312"); int dcount = 0; foreach (char ch in self.ToCharArray()) { if (coding.GetByteCount(ch.ToString()) == 2) dcount++; } string w = self.PadRight(length - dcount, c); return w; } public static bool IsDefault(this T self) where T : IEquatable { return self.Equals(default); } public static float Random(this float self) => UnityEngine.Random.Range(-self, self); public static int Random(this int self) => UnityEngine.Random.Range(-self, self); public static Location GetLocation(this Component self) { return new Location(self); } public static Location GetLocation(this GameObject self) { return new Location(self.transform); } public static T Random(this IEnumerable e) { return e.ElementAt(UnityEngine.Random.Range(0, e.Count())); } public static T Random(this T[] self) { return self[UnityEngine.Random.Range(0, self.Length)]; } public static bool IsNullOrEmpty(this string self) { return String.IsNullOrWhiteSpace(self); } public static bool IsValid(this string self) { return !self.IsNullOrEmpty(); } public static UnityEvent AddListener(this UnityEvent unityEvent, UnityAction call) { unityEvent.AddListener(call); return unityEvent; } public static string Combine(this string[] self) { if (self.IsNull()) { return string.Empty; } StringBuilder stringBuilder = new(); self.ForEach(x => { stringBuilder.Append(x); }); return stringBuilder.ToString(); } public static string Combine(this IEnumerable self, bool split = false) { StringBuilder stringBuilder = new StringBuilder(); if (self.IsNull()) { return string.Empty; } self.ForEach(x => { stringBuilder.Append(x); stringBuilder.Append(" "); if (split) { stringBuilder.Append("\n"); } }); return stringBuilder.ToString(); } public static float ToFloat(this string self) { if (string.IsNullOrEmpty(self)) return default; return float.Parse(self); } public static Vector3 MatchTarget(this ref Vector3 self, Vector3 pos, float normalizedTime, float start, float end) { if (normalizedTime >= start && normalizedTime <= end) { float process = normalizedTime / (end - start); Vector3 direction = pos - self; return Vector3.Lerp(default, direction, process); } return default; } public static Dictionary ToDictionary(this string jsonSrting, params string[] removes) { removes.ForEach(x => { jsonSrting = jsonSrting.Replace(x, string.Empty); }); var jsonObject = JObject.Parse(jsonSrting); var jTokens = jsonObject.Descendants().Where(p => !p.Any()); var tmpKeys = jTokens.Aggregate(new Dictionary(), (properties, jToken) => { properties.Add(jToken.Path, jToken.ToString()); return properties; }); return tmpKeys; } public static Dictionary JsonToDictionary(this string jsonSrting, params string[] replace) { replace.ForEach(x => { jsonSrting = jsonSrting.Replace(x, string.Empty); }); Dictionary dic = JsonConvert.DeserializeObject>(jsonSrting); return dic; } public static string DeleteLines(string text, int lineCount) { while (text.Split('\n').Length > lineCount) text = text.Remove(0, text.Split('\n')[0].Length + 1); return text; } public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp) { var tcs = new TaskCompletionSource(); asyncOp.completed += obj => { tcs.SetResult(null); }; return ((Task)tcs.Task).GetAwaiter(); } public static TaskAwaiter GetAwaiter(this System.Action action) { var tcs = new TaskCompletionSource(); action += () => { tcs.SetResult(null); }; return ((Task)tcs.Task).GetAwaiter(); } public static float GetDifference(this IEnumerable self) { return self.Max() - self.Min(); } public static void Toggle(this Behaviour self) { self.enabled = !self.enabled; } public static void SetEnabled(this UnityEngine.Behaviour self, bool value) { if (self) { self.enabled = value; } } public static T Or(params T[] ts) { for (int i = 0; i < ts.Length; i++) { var t = ts[i]; if (t != null && t.Equals(default)) { } else { return t; } } return default; } public static bool TryGetComponentsInParent(this GameObject self, out T[] components) { return TryGetComponentsInParent(self.transform, out components); } public static bool TryGetComponentsInParent(this Component self, out T[] components) { components = self.GetComponentsInParent(); return components.IsValid(); } public static bool TryGetComponentAny(this Component self, out T component) { component = self.GetComponentInChildren(); if (component is not null) { return true; } component = self.GetComponentInParent(); if (component is not null) { return true; } return false; } public static bool TryGetFirstOrDefault(this IEnumerable self, out T value) { value = default; if (self.IsValid()) { value = self.ElementAt(0); return true; } return default; } public static TValue GetOrDefault(this IDictionary self, TKey key) { TValue value = default; self.TryGetValue(key, out value); return value; ; } public static void DestoryChilds(this GameObject self) { if (self) { var list = self.GetComponentsInChildren().ToList(); list.TryRemove(self.transform); list.ForEach(x => { GameObject.Destroy(x.gameObject); }); } } public static bool Contains(this string self, IEnumerable strs, out string key) { bool result = false; string newKey = default; strs.ForEach(x => { if (self.Contains(x)) { result = true; newKey = x; return; } }); key = newKey; return result; } /// /// 带毫秒的字符转换成时间(DateTime)格式 /// 可处理格式:[2014-10-10 10:10:10,666 或 2014-10-10 10:10:10 666 或 2014-10-10 10:10:10.666] /// public static DateTime GetDateTime(this string dateTime) { string[] strArr = dateTime.Split(new char[] { '-', ' ', ':', ',', '.' }); DateTime dt = new DateTime(int.Parse(strArr[0]), int.Parse(strArr[1]), int.Parse(strArr[2]), int.Parse(strArr[3]), int.Parse(strArr[4]), int.Parse(strArr[5]), int.Parse(strArr[6])); return dt; } public static bool Equality(this IEnumerable self, IEnumerable other) { bool result = true; if (self.Count() != other.Count()) { return false; } self.ForEach(x => { if (other.Contains(x) == false) { result = false; return; } }); return result; } public static string ReservedRows(this string self, int length, bool reverse = false) { StringBuilder stringBuilder = new(self); var lines = self.Split("\n"); if (reverse) { lines.Reverse().ToList(); } if (lines.Length > length) { stringBuilder.Clear(); for (int i = lines.Length - length; i < lines.Length; i++) { var words = lines[i]; if (words is not "\n") { stringBuilder.Append(words); } stringBuilder.Append("\n"); } } return stringBuilder.ToString(); } } public static partial class ReflectionExtensions { public static void ForEachProties(this object self, UnityAction action = null) { self.GetType().GetProperties().ForEach(x => { Debug.Log(x.Name); if (x.GetCustomAttribute() == null && x.GetValue(self) is T t) { if (action is not null) action.Invoke(t); } }); } public static void ForEachFields(this object self, UnityAction action = null, UnityAction infoAction = null, UnityAction mixAction = null) { self.GetType().GetFields().ForEach(x => { if (x.GetCustomAttribute() == null && x.GetValue(self) is T t) { if (infoAction is not null) infoAction.Invoke(x); if (action is not null) action.Invoke(t); if (mixAction is not null) mixAction.Invoke(x, t); } }); } } public static partial class UIToolkitExtensions { public static void SetActive(this VisualElement self, bool active) { self.style.display = new(active ? DisplayStyle.Flex : DisplayStyle.None); } public static float GetOpacity(this VisualElement self) => self.style.opacity.value; public static void SetOpacity(this VisualElement self, float value) => self.style.opacity = new(value); public static void ScrollToBottom(this ScrollView self) { self.verticalScroller.value = self.verticalScroller.highValue > 0 ? self.verticalScroller.highValue : 0; } public static async void ScrollToBottomAutomatic(this ScrollView self, float delay = 0.02f) { if (self.verticalScroller.value == self.verticalScroller.highValue) { try { await Task.Delay(TimeSpan.FromSeconds(delay), BITApp.CancellationTokenSource.Token); ScrollToBottom(self); } catch (OperationCanceledException) { } catch (System.Exception) { throw; } } } } }