BITKit/Packages/Runtime~/Unity/Common/Scripts/Utility/Extensions.cs

541 lines
18 KiB
C#
Raw Normal View History

2023-06-05 19:57:17 +08:00
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;
}
2023-06-29 14:57:11 +08:00
public static Vector3 TransientRotationAxis(Vector3 transientAxis)
2023-06-05 19:57:17 +08:00
{
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;
2023-06-29 14:57:11 +08:00
int GetAlign(float _self)
2023-06-05 19:57:17 +08:00
{
2023-06-29 14:57:11 +08:00
var size = (int)_self / snapSize;
var remainder = _self % snapSize;
2023-06-05 19:57:17 +08:00
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;
2023-06-29 14:57:11 +08:00
if (Math.Abs(MathF.Abs(addValue) - Mathf.Abs(subtractValue)) < 0.01f)
2023-06-05 19:57:17 +08:00
{
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<T>(this T self) where T : IEquatable<T>
{
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<T>(this IEnumerable<T> e)
{
return e.ElementAt(UnityEngine.Random.Range(0, e.Count()));
}
public static T Random<T>(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<string> 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<string, string> 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<string, string>(),
(properties, jToken) =>
{
properties.Add(jToken.Path, jToken.ToString());
return properties;
});
return tmpKeys;
}
public static Dictionary<string, string> JsonToDictionary(this string jsonSrting, params string[] replace)
{
replace.ForEach(x =>
{
jsonSrting = jsonSrting.Replace(x, string.Empty);
});
Dictionary<string, string> dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(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<object>();
asyncOp.completed += obj => { tcs.SetResult(null); };
return ((Task)tcs.Task).GetAwaiter();
}
public static TaskAwaiter GetAwaiter(this System.Action action)
{
var tcs = new TaskCompletionSource<object>();
action += () => { tcs.SetResult(null); };
return ((Task)tcs.Task).GetAwaiter();
}
public static float GetDifference(this IEnumerable<float> 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<T>(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<T>(this GameObject self, out T[] components)
{
return TryGetComponentsInParent(self.transform, out components);
}
public static bool TryGetComponentsInParent<T>(this Component self, out T[] components)
{
components = self.GetComponentsInParent<T>();
return components.IsValid();
}
public static bool TryGetComponentAny<T>(this Component self, out T component)
{
component = self.GetComponentInChildren<T>();
if (component is not null)
{
return true;
}
component = self.GetComponentInParent<T>();
if (component is not null)
{
return true;
}
return false;
}
public static bool TryGetFirstOrDefault<T>(this IEnumerable<T> self, out T value)
{
value = default;
if (self.IsValid())
{
value = self.ElementAt(0);
return true;
}
return default;
}
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> 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<Transform>().ToList();
list.TryRemove(self.transform);
list.ForEach(x =>
{
GameObject.Destroy(x.gameObject);
});
}
}
public static bool Contains(this string self, IEnumerable<string> 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;
}
/// <summary>
/// 带毫秒的字符转换成时间DateTime格式
/// 可处理格式:[2014-10-10 10:10:10,666 或 2014-10-10 10:10:10 666 或 2014-10-10 10:10:10.666]
/// </summary>
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<T>(this IEnumerable<T> self, IEnumerable<T> 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<T>(this object self, UnityAction<T> action = null)
{
self.GetType().GetProperties().ForEach(x =>
{
Debug.Log(x.Name);
if (x.GetCustomAttribute<ObsoleteAttribute>() == null && x.GetValue(self) is T t)
{
if (action is not null) action.Invoke(t);
}
});
}
public static void ForEachFields<T>(this object self, UnityAction<T> action = null, UnityAction<FieldInfo> infoAction = null, UnityAction<FieldInfo, T> mixAction = null)
{
self.GetType().GetFields().ForEach(x =>
{
if (x.GetCustomAttribute<ObsoleteAttribute>() == 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;
}
}
}
}
}