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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|