1
This commit is contained in:
20
Unity/Scripts/Utility/AnimatorUtils.cs
Normal file
20
Unity/Scripts/Utility/AnimatorUtils.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit
|
||||
{
|
||||
public struct AnimatorParameter
|
||||
{
|
||||
public AnimatorControllerParameterType type;
|
||||
public string name;
|
||||
public object value;
|
||||
public T Get<T>()
|
||||
{
|
||||
if (value is T t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
7
Unity/Scripts/Utility/Attribute.cs
Normal file
7
Unity/Scripts/Utility/Attribute.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit
|
||||
{
|
||||
}
|
39
Unity/Scripts/Utility/Behaviour.cs
Normal file
39
Unity/Scripts/Utility/Behaviour.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine.UIElements;
|
||||
namespace BITKit
|
||||
{
|
||||
|
||||
public abstract class BITBehavior : SerializedMonoBehaviour, ICustomInspector
|
||||
{
|
||||
public VisualTreeAsset customTreeAsset;
|
||||
public virtual void OnAwake() { }
|
||||
public virtual void OnStart() { }
|
||||
public virtual void OnStop() { }
|
||||
public virtual void OnUpdate(float deltaTime) { }
|
||||
public virtual void OnFixedUpdate(float deltaTime) { }
|
||||
public virtual void OnLateUpdate(float deltaTime) { }
|
||||
public virtual void OnDestroyComponent() { }
|
||||
public virtual void SetActive(bool active) { }
|
||||
public virtual Transform GetTransform() => transform;
|
||||
public void Toggle()
|
||||
{
|
||||
enabled = !enabled;
|
||||
}
|
||||
public virtual string GetName()
|
||||
{
|
||||
return gameObject.name;
|
||||
}
|
||||
public virtual object GetDiagnostics()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
public VisualElement GetVisualElement()
|
||||
{
|
||||
return customTreeAsset ? customTreeAsset.CloneTree() : null;
|
||||
}
|
||||
}
|
||||
}
|
27
Unity/Scripts/Utility/DeltaTimer.cs
Normal file
27
Unity/Scripts/Utility/DeltaTimer.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit
|
||||
{
|
||||
public class DeltaTimer
|
||||
{
|
||||
public static implicit operator int(DeltaTimer timer)
|
||||
{
|
||||
return ((int)(1f / timer.deltaTime));
|
||||
}
|
||||
public static implicit operator string(DeltaTimer timer)
|
||||
{
|
||||
return ((int)timer).ToString();
|
||||
}
|
||||
float deltaTime = 0.0f;
|
||||
// Update is called once per frame
|
||||
public void Update(float unscaleDeltaTime = -1)
|
||||
{
|
||||
if (unscaleDeltaTime is -1)
|
||||
{
|
||||
unscaleDeltaTime = Time.unscaledDeltaTime;
|
||||
}
|
||||
deltaTime += (unscaleDeltaTime - deltaTime) * 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
171
Unity/Scripts/Utility/Editor/BITInspector.cs
Normal file
171
Unity/Scripts/Utility/Editor/BITInspector.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Reflection;
|
||||
using UnityEngine.AddressableAssets;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using Editor = UnityEditor.Editor;
|
||||
using UnityEditor.UIElements;
|
||||
#else
|
||||
using Editor=BITKit.Constant.EmetyClass;
|
||||
#endif
|
||||
namespace BITKit
|
||||
{
|
||||
public class BITAttribute : System.Attribute
|
||||
{
|
||||
|
||||
}
|
||||
public class ServerRpcAttribute : System.Attribute
|
||||
{
|
||||
|
||||
}
|
||||
public class ClientRpcAttribute : System.Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public class BITInspector<T> : Editor
|
||||
{
|
||||
const string ussName = "BITInspector";
|
||||
public class VisualElementCreator
|
||||
{
|
||||
public static implicit operator VisualElement(VisualElementCreator self)
|
||||
{
|
||||
return self.root;
|
||||
}
|
||||
public VisualElement root;
|
||||
public VE Create<VE>() where VE : VisualElement, new()
|
||||
{
|
||||
root = root ?? new();
|
||||
var ve = new VE();
|
||||
root.Add(ve);
|
||||
return ve;
|
||||
}
|
||||
}
|
||||
protected VisualElementCreator root = new();
|
||||
protected T agent;
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
if (serializedObject.targetObject is ICustomInspector inspector && inspector.GetVisualElement() is not null)
|
||||
{
|
||||
return inspector.GetVisualElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
FillDefaultInspector();
|
||||
return root;
|
||||
}
|
||||
}
|
||||
protected Label CreateSubTitle(string value)
|
||||
{
|
||||
var label = root.Create<Label>();
|
||||
label.text = value;
|
||||
label.AddToClassList("subTitle");
|
||||
return label;
|
||||
}
|
||||
void Awake()
|
||||
{
|
||||
root.root = new();
|
||||
|
||||
if (serializedObject.targetObject is T value)
|
||||
{
|
||||
agent = value;
|
||||
}
|
||||
}
|
||||
void OnEnable()
|
||||
{
|
||||
StyleSheet css = Addressables.LoadAssetAsync<StyleSheet>(ussName).WaitForCompletion();
|
||||
|
||||
root.root.styleSheets.Add(css);
|
||||
|
||||
EditorApplication.update += OnUpdate;
|
||||
}
|
||||
void OnDisable()
|
||||
{
|
||||
EditorApplication.update -= OnUpdate;
|
||||
}
|
||||
protected virtual void OnUpdate()
|
||||
{
|
||||
|
||||
}
|
||||
protected void FillDefaultInspector()
|
||||
{
|
||||
FillDefaultInspector(root, serializedObject, true);
|
||||
}
|
||||
public static void FillDefaultInspector(VisualElement container, SerializedObject serializedObject, bool hideScript)
|
||||
{
|
||||
SerializedProperty property = serializedObject.GetIterator();
|
||||
if (property.NextVisible(true)) // Expand first child.
|
||||
{
|
||||
do
|
||||
{
|
||||
if (property.propertyPath == "m_Script" && hideScript)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var type = serializedObject.targetObject.GetType().GetField(property.name);
|
||||
var field = new PropertyField(property);
|
||||
|
||||
|
||||
|
||||
field.name = "PropertyField:" + property.propertyPath;
|
||||
|
||||
|
||||
if (property.propertyPath == "m_Script" && serializedObject.targetObject != null)
|
||||
{
|
||||
field.SetEnabled(false);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (type is not null)
|
||||
{
|
||||
var header = type.GetCustomAttribute<HeaderAttribute>();
|
||||
if (header is not null)
|
||||
{
|
||||
Label label = new Label(header.header);
|
||||
label.AddToClassList("subTitle");
|
||||
container.Add(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
|
||||
container.Add(field);
|
||||
}
|
||||
while (property.NextVisible(false));
|
||||
|
||||
foreach (var method in serializedObject.targetObject.GetType().GetMethods())
|
||||
{
|
||||
if (method.GetCustomAttribute<BITAttribute>() is not null)
|
||||
{
|
||||
if (method.GetParameters().Length is 0)
|
||||
{
|
||||
var button = new Button(() => method.Invoke(serializedObject.targetObject, null));
|
||||
button.text = method.Name;
|
||||
|
||||
container.Add(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public class BITProperty : PropertyDrawer
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
PropertyField propertyField = new(property);
|
||||
return propertyField;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
541
Unity/Scripts/Utility/Extensions.cs
Normal file
541
Unity/Scripts/Utility/Extensions.cs
Normal file
@@ -0,0 +1,541 @@
|
||||
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(this 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 (MathF.Abs(addValue) == Mathf.Abs(subtractValue))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
66
Unity/Scripts/Utility/Path.cs
Normal file
66
Unity/Scripts/Utility/Path.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
namespace BITKit
|
||||
{
|
||||
public static partial class Utility
|
||||
{
|
||||
public static class Path
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
static void Init()
|
||||
{
|
||||
dataPath = Application.dataPath;
|
||||
persistentDataPath = Application.persistentDataPath;
|
||||
currentDirectory = System.Environment.CurrentDirectory;
|
||||
}
|
||||
public static string dataPath { get; private set; }
|
||||
public static string persistentDataPath { get; private set; }
|
||||
public static string currentDirectory { get; private set; }
|
||||
public static string Get(params string[] nextPaths)
|
||||
{
|
||||
currentDirectory = System.Environment.CurrentDirectory;
|
||||
var path = currentDirectory;
|
||||
var filePath = System.IO.Path.Combine(currentDirectory, "Assembly-CSharp.csproj");
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
path = System.IO.Path.Combine(path, "Assets");
|
||||
}
|
||||
foreach (var nextPath in nextPaths)
|
||||
{
|
||||
path = System.IO.Path.Combine(path, nextPath);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
public static string CombinePath(params string[] nextPaths)
|
||||
{
|
||||
string path = nextPaths[0];
|
||||
for (int i = 1; i < nextPaths.Length - 1; i++)
|
||||
{
|
||||
path += "/" + nextPaths[i];
|
||||
}
|
||||
path += "/" + nextPaths.Last();
|
||||
return path;
|
||||
}
|
||||
public static IEnumerable<string> ReadAllFile(string folderPath, string filter = null)
|
||||
{
|
||||
if (Directory.Exists(folderPath))
|
||||
{
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
|
||||
|
||||
var files = directoryInfo.GetFiles()
|
||||
.OrderBy(x => x.LastWriteTime)
|
||||
.Select(x => x);
|
||||
if (filter.IsValid())
|
||||
{
|
||||
files = files.Where(x => x.Name.Contains(filter));
|
||||
}
|
||||
return files.Select(x => x.ToString());
|
||||
}
|
||||
return new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
Unity/Scripts/Utility/PerformanceTimer.cs
Normal file
50
Unity/Scripts/Utility/PerformanceTimer.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System;
|
||||
namespace BITKit
|
||||
{
|
||||
class PerformanceTimer
|
||||
{
|
||||
[DllImport("Kernel32.dll")]
|
||||
private static extern bool QueryPerformanceCounter(
|
||||
out long lpPerformanceCount);
|
||||
|
||||
[DllImport("Kernel32.dll")]
|
||||
private static extern bool QueryPerformanceFrequency(
|
||||
out long lpFrequency);
|
||||
|
||||
private long startTime, stopTime;
|
||||
private long freq;
|
||||
|
||||
public PerformanceTimer()
|
||||
{
|
||||
startTime = 0;
|
||||
stopTime = 0;
|
||||
|
||||
if (QueryPerformanceFrequency(out freq) == false)
|
||||
{
|
||||
throw new Exception("Timer not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
QueryPerformanceCounter(out startTime);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
QueryPerformanceCounter(out stopTime);
|
||||
}
|
||||
|
||||
public double Duration
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)(stopTime - startTime) / (double)freq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
35
Unity/Scripts/Utility/Pool.cs
Normal file
35
Unity/Scripts/Utility/Pool.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
namespace BITKit
|
||||
{
|
||||
[System.Serializable]
|
||||
public class UnityPool<T> where T : Component
|
||||
{
|
||||
public UnityPool()
|
||||
{
|
||||
this.pool = new(Spawn, OnGet, OnReturn, OnDestroy, maxSize: 16);
|
||||
}
|
||||
[Header(Constant.Header.Prefabs)]
|
||||
public T prefab;
|
||||
[Header(Constant.Header.Gameobjects)]
|
||||
public Transform root;
|
||||
[Header(Constant.Header.InternalVariables)]
|
||||
ObjectPool<T> pool;
|
||||
public T Get(T element = null, Transform root = null)
|
||||
{
|
||||
if (element is not null)
|
||||
prefab = element;
|
||||
if (root is not null)
|
||||
this.root = root;
|
||||
return pool.Get();
|
||||
}
|
||||
public void Return(T element) => pool.Release(element);
|
||||
T Spawn() => Transform.Instantiate(prefab, root);
|
||||
void OnGet(T element) => element.gameObject.SetActive(true);
|
||||
void OnReturn(T element) => element.gameObject.SetActive(false);
|
||||
void OnDestroy(T element) => GameObject.Destroy(element.gameObject);
|
||||
}
|
||||
}
|
45
Unity/Scripts/Utility/Processor.cs
Normal file
45
Unity/Scripts/Utility/Processor.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit
|
||||
{
|
||||
/// <summary>加工系统.处理系统,加工一个数据后返回,处理一个数据后返回</summary>
|
||||
public interface IProcessor
|
||||
{
|
||||
T GetContext<T>(string key, T value);
|
||||
void AddProcessor<T>(string key, Func<T, T> func);
|
||||
void RemoveProcessor<T>(string key, Func<T, T> func);
|
||||
T GetContext<T>(T value = default);
|
||||
void AddProcessor<T>(Func<T, T> func);
|
||||
void RemoveProcessor<T>(Func<T, T> func);
|
||||
}
|
||||
public class Processor : IProcessor
|
||||
{
|
||||
public Dictionary<string, List<object>> dictionary = new();
|
||||
public T GetContext<T>(T value = default) => GetContext<T>(key, value);
|
||||
public void AddProcessor<T>(Func<T, T> func) => AddProcessor<T>(key, func);
|
||||
public void RemoveProcessor<T>(Func<T, T> func) => RemoveProcessor<T>(key, func);
|
||||
string key => nameof(Processor);
|
||||
public T GetContext<T>(string key, T value)
|
||||
{
|
||||
key = string.Empty.GetType<T>();
|
||||
dictionary.Get(key).ForEach(x =>
|
||||
{
|
||||
var func = x as Func<T, T>;
|
||||
value = func.Invoke(value);
|
||||
});
|
||||
return value;
|
||||
}
|
||||
public void AddProcessor<T>(string key, Func<T, T> func)
|
||||
{
|
||||
key = string.Empty.GetType<T>();
|
||||
dictionary.Get(key).Add(func);
|
||||
}
|
||||
public void RemoveProcessor<T>(string key, Func<T, T> func)
|
||||
{
|
||||
key = string.Empty.GetType<T>();
|
||||
dictionary.Get(key).Remove(func);
|
||||
}
|
||||
}
|
||||
}
|
26
Unity/Scripts/Utility/ScriptableObjectHelper.cs
Normal file
26
Unity/Scripts/Utility/ScriptableObjectHelper.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
namespace BITKit
|
||||
{
|
||||
public static class ScriptableObjectHelper
|
||||
{
|
||||
public static T Get<T>() where T : ScriptableObject
|
||||
{
|
||||
string name = typeof(T).Name;
|
||||
T so = Resources.Load<T>(name);
|
||||
#if UNITY_EDITOR
|
||||
if (so is null)
|
||||
{
|
||||
so = ScriptableObject.CreateInstance<T>();
|
||||
AssetDatabase.CreateAsset(so, $"Assets/Resources/{name}.asset");
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
#endif
|
||||
return so;
|
||||
}
|
||||
}
|
||||
}
|
57
Unity/Scripts/Utility/Tests/CacheTest.cs
Normal file
57
Unity/Scripts/Utility/Tests/CacheTest.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using BITKit.IO;
|
||||
namespace BITKit
|
||||
{
|
||||
|
||||
public class CacheTest
|
||||
{
|
||||
public struct MethodIndex
|
||||
{
|
||||
public Type type;
|
||||
public string methodName;
|
||||
public MethodInfo GetMethodInfo()
|
||||
{
|
||||
return type.GetMethod(methodName);
|
||||
}
|
||||
}
|
||||
string path => PathHelper.GetFilePath("Cache", "CacheTest.cache");
|
||||
[Test]
|
||||
public void WriteCache()
|
||||
{
|
||||
var type = this.GetType();
|
||||
|
||||
MethodIndex value = new();
|
||||
value.type = type;
|
||||
value.methodName = nameof(ReadCache);
|
||||
|
||||
BITCache.Write(nameof(CacheTest), value);
|
||||
|
||||
Debug.Log($"已生成缓存:{path}");
|
||||
}
|
||||
[Test]
|
||||
public void ReadCache()
|
||||
{
|
||||
if (BITCache.Read<MethodInfo>(path, out var info))
|
||||
{
|
||||
Debug.Log("已读取到缓存");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("未读取到缓存");
|
||||
}
|
||||
}
|
||||
[Test]
|
||||
public void ClearCache()
|
||||
{
|
||||
BITCache.Guid = Guid.NewGuid();
|
||||
}
|
||||
}
|
||||
}
|
21
Unity/Scripts/Utility/Tests/DateTimeTester.cs
Normal file
21
Unity/Scripts/Utility/Tests/DateTimeTester.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
namespace BITKit
|
||||
{
|
||||
public class DateTimeTester
|
||||
{
|
||||
[Test]
|
||||
public void GetTicks()
|
||||
{
|
||||
Debug.Log(DateTime.Now.Ticks);
|
||||
var time = TimeUtils.GetNow();
|
||||
Debug.Log($"long:\t{time}");
|
||||
Debug.Log($"int:\t{(int)time}");
|
||||
Debug.Log($"float:\t{(float)time}");
|
||||
}
|
||||
}
|
||||
}
|
26
Unity/Scripts/Utility/Tests/FloatTest.cs
Normal file
26
Unity/Scripts/Utility/Tests/FloatTest.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
using UnityEngine.TestTools;
|
||||
using System.Linq;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace BITKit
|
||||
{
|
||||
public class FloatTest
|
||||
{
|
||||
[Test]
|
||||
public void AddRandom()
|
||||
{
|
||||
float currentValue = 0;
|
||||
for (int i = 0; i < Random.Range(1,4); i++)
|
||||
{
|
||||
float newValue = Random.Range(0, 8f);
|
||||
Debug.Log($"{currentValue}+{newValue} = {currentValue+=newValue}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
Unity/Scripts/Utility/Tests/GenericEventTest.cs
Normal file
30
Unity/Scripts/Utility/Tests/GenericEventTest.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using BITKit.IO;
|
||||
using System.Text;
|
||||
namespace BITKit
|
||||
{
|
||||
public class GenericEventTest
|
||||
{
|
||||
[Test]
|
||||
public void TestInvokeByType()
|
||||
{
|
||||
GenericEvent genericEvent = new();
|
||||
genericEvent.AddListener<string>(OnGetString);
|
||||
|
||||
genericEvent.Invoke<string>("Value 123");
|
||||
genericEvent.Invoke(typeof(string).Name, "Value 321" as object);
|
||||
void OnGetString(string value)
|
||||
{
|
||||
Debug.Log($"事件回调:{value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
Unity/Scripts/Utility/Tests/IEnumerableTest.cs
Normal file
27
Unity/Scripts/Utility/Tests/IEnumerableTest.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Newtonsoft.Json;
|
||||
namespace BITKit
|
||||
{
|
||||
public class IEnumerableTest
|
||||
{
|
||||
[Test]
|
||||
public void AppendIEnumerable()
|
||||
{
|
||||
List<int> list = new();
|
||||
|
||||
list.CreateOrAddIfEmety(list,() => 1);
|
||||
list.Add(2);
|
||||
|
||||
int[] array = new int[0];
|
||||
array.CreateOrAddIfEmety(array,() => 1);
|
||||
|
||||
Debug.Log("Length Should Be 2");
|
||||
Debug.Log($"List:{JsonConvert.SerializeObject(list, Formatting.Indented)}");
|
||||
Debug.Log($"Array:{JsonConvert.SerializeObject(array, Formatting.Indented)}");
|
||||
}
|
||||
}
|
||||
}
|
46
Unity/Scripts/Utility/Tests/MemoryStreamTest.cs
Normal file
46
Unity/Scripts/Utility/Tests/MemoryStreamTest.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using BITKit.IO;
|
||||
using System.Text;
|
||||
namespace BITKit
|
||||
{
|
||||
public class MemoryStreamTest
|
||||
{
|
||||
[Test]
|
||||
public void WriteStringToMemorySteam()
|
||||
{
|
||||
var _str = nameof(MemoryStreamTest);
|
||||
var _int = 256;
|
||||
var _float = 3.1415926;
|
||||
byte[] bytes;
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter writer = new(ms))
|
||||
{
|
||||
writer.Write(_str);
|
||||
writer.Write(_int);
|
||||
writer.Write(_float);
|
||||
}
|
||||
bytes = ms.ToArray();
|
||||
}
|
||||
Debug.Log($"输入:\nstring:{_str}\nint{_int}\nfloat{_float}");
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
{
|
||||
using (var reader = new BinaryReader(ms))
|
||||
{
|
||||
_str = reader.ReadString();
|
||||
_int = reader.ReadInt32();
|
||||
_float = (float)reader.ReadDouble();
|
||||
}
|
||||
}
|
||||
Debug.Log($":\nstring:{_str}\nint{_int}\nfloat{_float}");
|
||||
}
|
||||
}
|
||||
}
|
57
Unity/Scripts/Utility/Tests/ObjectMatcherTest.cs
Normal file
57
Unity/Scripts/Utility/Tests/ObjectMatcherTest.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using BITKit.IO;
|
||||
using System.Text;
|
||||
namespace BITKit
|
||||
{
|
||||
public class ObjectMatcherTest
|
||||
{
|
||||
[Test]
|
||||
public void TestObjectMatcher()
|
||||
{
|
||||
ObjectMatcher<string, string> matcher = new();
|
||||
matcher.list = new ObjectElement<string, string>[]
|
||||
{
|
||||
new("xyz","x","y","z"),
|
||||
new("XYZ","X","Y","Z"),
|
||||
new("123","1","2","3"),
|
||||
new("BulletHit","Hitbox","Blood"),
|
||||
};
|
||||
string[][] useCases = new string[][]{
|
||||
new string[]{
|
||||
"x","y","z"
|
||||
},
|
||||
new string[]{
|
||||
"w","y","x","z"
|
||||
},
|
||||
new string[]{
|
||||
"X","y","Z"
|
||||
},
|
||||
new string[]{
|
||||
"3","1","2"
|
||||
},
|
||||
new string[]{
|
||||
"1","5","7"
|
||||
},
|
||||
new string[]
|
||||
{
|
||||
"BulletHit","Hitbox","Blood"
|
||||
}
|
||||
};
|
||||
StringBuilder stringBuilder = new();
|
||||
foreach (var useCase in useCases)
|
||||
{
|
||||
stringBuilder.AppendLine($"当前用例:{JsonConvert.SerializeObject(useCase)}");
|
||||
stringBuilder.AppendLine($"当前返回:{matcher.TryMatch(out string value, useCase)} @{value}");
|
||||
}
|
||||
Debug.Log(stringBuilder);
|
||||
}
|
||||
}
|
||||
}
|
29
Unity/Scripts/Utility/Tests/ProcessorTester.cs
Normal file
29
Unity/Scripts/Utility/Tests/ProcessorTester.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
namespace BITKit
|
||||
{
|
||||
public class ProcessorTester
|
||||
{
|
||||
[Test]
|
||||
public void Test()
|
||||
{
|
||||
Processor processor = new();
|
||||
processor.AddProcessor<int>("GetDamage", ReduceDamage);
|
||||
|
||||
var damage = processor.GetContext<int>("GetDamage", 64);
|
||||
|
||||
Debug.Log(damage);
|
||||
processor.RemoveProcessor<int>("GetDamage", ReduceDamage);
|
||||
|
||||
damage = processor.GetContext<int>("GetDamage", 64);
|
||||
Debug.Log(damage);
|
||||
}
|
||||
int ReduceDamage(int damage)
|
||||
{
|
||||
return damage / 2;
|
||||
}
|
||||
}
|
||||
}
|
31
Unity/Scripts/Utility/Tests/PropertyTest.cs
Normal file
31
Unity/Scripts/Utility/Tests/PropertyTest.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
using UnityEngine.TestTools;
|
||||
using System.Linq;
|
||||
namespace BITKit
|
||||
{
|
||||
public class PropertyTest
|
||||
{
|
||||
[Test]
|
||||
public void TestProperty()
|
||||
{
|
||||
TestValue(64);
|
||||
TestValue(3.1415926);
|
||||
TestValue(true);
|
||||
TestValue(DateTime.Now);
|
||||
}
|
||||
void TestValue<T>(T value)
|
||||
{
|
||||
Property property = new Property();
|
||||
property.SetProperty(value);
|
||||
|
||||
var output = property.GetProperty<T>();
|
||||
|
||||
Debug.Log($"<22><><EFBFBD><EFBFBD>ֵ:{value},<2C><><EFBFBD><EFBFBD>ֵ:{output},<2C><><EFBFBD><EFBFBD>:{value.Equals(output)}");
|
||||
}
|
||||
}
|
||||
}
|
142
Unity/Scripts/Utility/Tests/StringTest.cs
Normal file
142
Unity/Scripts/Utility/Tests/StringTest.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
using UnityEngine.TestTools;
|
||||
using System.Linq;
|
||||
namespace BITKit
|
||||
{
|
||||
public class StringTest
|
||||
{
|
||||
[Test]
|
||||
public void JoinString()
|
||||
{
|
||||
List<string> stringList = new()
|
||||
{
|
||||
"UX",
|
||||
"Test",
|
||||
"Creator"
|
||||
};
|
||||
Debug.Log(string.Join("/",stringList));
|
||||
}
|
||||
[Test]
|
||||
public void SpliteNamespace()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
List<string> ignoreNamespaces = new()
|
||||
{
|
||||
"System",
|
||||
"UnityEngine",
|
||||
"Unity",
|
||||
"Microsoft",
|
||||
"UnityEditor",
|
||||
"Google",
|
||||
"Mono",
|
||||
"ZXing",
|
||||
"ImmersiveVRTools",
|
||||
"MonKey",
|
||||
"FLib",
|
||||
"Kcp",
|
||||
"Udx",
|
||||
"Sirenix",
|
||||
"TMPro",
|
||||
"RotaryHeart",
|
||||
"Cinemachine",
|
||||
"ParadoxNotion",
|
||||
"Net",
|
||||
"VSCodeEditor",
|
||||
"AOT",
|
||||
"UnityEditorInternal",
|
||||
"UnityEngineInternal",
|
||||
"JetBrains",
|
||||
"Bee",
|
||||
"NotInvited",
|
||||
"HighlightPlus",
|
||||
"DG",
|
||||
"Hierarchy2",
|
||||
"Cysharp",
|
||||
"JetBrains",
|
||||
"Packages",
|
||||
"Newtonsoft_X",
|
||||
"Binding",
|
||||
"NodeCanvas",
|
||||
"SaveDuringPlay",
|
||||
"LimWorks",
|
||||
"MagicaCloth2",
|
||||
"FastScriptReload",
|
||||
"ParrelSync",
|
||||
"KinematicCharacterController",
|
||||
"LimWorksEditor",
|
||||
"BuildComponent",
|
||||
"dnlib",
|
||||
"BigIntegerLibrary",
|
||||
"Ionic",
|
||||
"log4net",
|
||||
"DG",
|
||||
"ImmersiveVrToolsCommon",
|
||||
"NUnit",
|
||||
"HarmonyLib",
|
||||
"MonoMod",
|
||||
"WebDav",
|
||||
"PlasticGui",
|
||||
"Codice",
|
||||
"GluonGui",
|
||||
"PlasticPipe",
|
||||
"XDiffGui",
|
||||
"MacFsWatcher",
|
||||
"MacUI",
|
||||
"PlayerBuildProgramLibrary",
|
||||
"ExCSS",
|
||||
"ScriptCompilationBuildProgram",
|
||||
"BeeBuildProgramCommon",
|
||||
"Accessibility",
|
||||
"CodiceApp",
|
||||
"Newtonsoft",
|
||||
"MergetoolGui",
|
||||
"TreeEditor",
|
||||
"MackySoft",
|
||||
"FullscreenEditor",
|
||||
|
||||
};
|
||||
var allTypes =new List<Type>();
|
||||
var supportTypes=new List<Type>();
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
try
|
||||
{
|
||||
allTypes.AddRange(assembly.GetExportedTypes());
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
stringBuilder.AppendLine($"以获取到类型:{allTypes.Count()}个");
|
||||
foreach (var type in allTypes)
|
||||
{
|
||||
var typeName = type.Name;
|
||||
var nameSpace = type.Namespace;
|
||||
var rootNamespace =string.IsNullOrEmpty(nameSpace)?string.Empty : nameSpace.Split(@".").First();
|
||||
var contrast = ignoreNamespaces.Contains(rootNamespace);
|
||||
//stringBuilder.AppendLine($"类型名称:{typeName}\t命名空间{nameSpace}\t根命名空间:{rootNamespace}\t对比结果:{contrast}");
|
||||
if(contrast)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
supportTypes.Add(type);
|
||||
}
|
||||
}
|
||||
stringBuilder.AppendLine($"所有类型{allTypes.Count()}个\t支持类型{supportTypes.Count}");
|
||||
stringBuilder.AppendLine("已支持的命名空间:");
|
||||
foreach (var x in supportTypes.Select(x=>x.Namespace).Distinct())
|
||||
{
|
||||
stringBuilder.AppendLine(x);
|
||||
}
|
||||
Debug.Log(stringBuilder);
|
||||
}
|
||||
}
|
||||
}
|
26
Unity/Scripts/Utility/Tests/Tests.asmdef
Normal file
26
Unity/Scripts/Utility/Tests/Tests.asmdef
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "Tests",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner",
|
||||
"BITKits",
|
||||
"BITKit"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll",
|
||||
"Newtonsoft.Json.dll"
|
||||
],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
22
Unity/Scripts/Utility/TextureHelper.cs
Normal file
22
Unity/Scripts/Utility/TextureHelper.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit
|
||||
{
|
||||
|
||||
public static partial class TextureHelper
|
||||
{
|
||||
public static Texture2D ToTexture2D(this RenderTexture rTex)
|
||||
{
|
||||
Texture2D tex = new Texture2D(rTex.width, rTex.height, TextureFormat.RGB24, false);
|
||||
var old_rt = RenderTexture.active;
|
||||
RenderTexture.active = rTex;
|
||||
|
||||
tex.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0);
|
||||
tex.Apply();
|
||||
|
||||
RenderTexture.active = old_rt;
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
}
|
68
Unity/Scripts/Utility/Time.cs
Normal file
68
Unity/Scripts/Utility/Time.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit
|
||||
{
|
||||
public static class TimeUtils
|
||||
{
|
||||
///<summary>
|
||||
///2023-02-45 15:02:45:628
|
||||
///</summary>
|
||||
public const string dateTimeFormat = "yyyy-MM-dd HH:mm:ss:fff";
|
||||
/// <summary>
|
||||
/// 带毫秒的字符转换成时间(DateTime)格式
|
||||
/// 可处理格式:[2014-10-10 10:10:10,666 或 2014-10-10 10:10:10 666 或 2014-10-10 10:10:10.666]
|
||||
/// </summary>
|
||||
/// 2022-12-30 15:39:48:795
|
||||
/// 20080501T08:30:52Z"
|
||||
/// yyyyMMddTHH:mm:ssZ
|
||||
public static DateTime GetDateTime(string dateTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
return DateTime.ParseExact(dateTime, dateTimeFormat, null);
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetDateTime_SCADA(dateTime);
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
Debug.LogWarning($"{dateTime}\n{dateTimeFormat}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public static float GetNow(DateTime now = default)
|
||||
{
|
||||
now = now == default ? DateTime.Now : now;
|
||||
float time = 0;
|
||||
time += now.Hour * 60 * 60;
|
||||
time += now.Minute * 60;
|
||||
time += now.Second;
|
||||
time += now.Millisecond * 0.001f;
|
||||
return time;
|
||||
}
|
||||
public static string GetNowString(DateTime now = default)
|
||||
{
|
||||
now = now == default ? DateTime.Now : now;
|
||||
return now.ToString(dateTimeFormat);
|
||||
}
|
||||
static DateTime GetDateTime_SCADA(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;
|
||||
}
|
||||
}
|
||||
}
|
46
Unity/Scripts/Utility/UnityWebRequestAwaiter.cs
Normal file
46
Unity/Scripts/Utility/UnityWebRequestAwaiter.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
public class UnityWebRequestAwaiter : INotifyCompletion
|
||||
{
|
||||
private UnityWebRequestAsyncOperation asyncOp;
|
||||
private Action continuation;
|
||||
|
||||
public UnityWebRequestAwaiter(UnityWebRequestAsyncOperation asyncOp)
|
||||
{
|
||||
this.asyncOp = asyncOp;
|
||||
asyncOp.completed += OnRequestCompleted;
|
||||
}
|
||||
|
||||
public bool IsCompleted { get { return asyncOp.isDone; } }
|
||||
|
||||
public void GetResult() { }
|
||||
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
this.continuation = continuation;
|
||||
}
|
||||
|
||||
private void OnRequestCompleted(AsyncOperation obj)
|
||||
{
|
||||
if (continuation != null)
|
||||
continuation();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExtensionMethods
|
||||
{
|
||||
public static UnityWebRequestAwaiter GetAwaiter(this UnityWebRequestAsyncOperation asyncOp)
|
||||
{
|
||||
return new UnityWebRequestAwaiter(asyncOp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Usage example:
|
||||
UnityWebRequest www = new UnityWebRequest();
|
||||
// ...
|
||||
await www.SendWebRequest();
|
||||
Debug.Log(req.downloadHandler.text);
|
||||
*/
|
268
Unity/Scripts/Utility/Utility.cs
Normal file
268
Unity/Scripts/Utility/Utility.cs
Normal file
@@ -0,0 +1,268 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UIElements;
|
||||
using Sirenix.OdinInspector;
|
||||
namespace BITKit
|
||||
{
|
||||
public abstract class Provider : MonoBehaviour, IProvider
|
||||
{
|
||||
public virtual T Get<T>()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public abstract void Set<T>(T obj);
|
||||
}
|
||||
public abstract class Provider<T> : Provider, IProvider<T>
|
||||
{
|
||||
public abstract T Get();
|
||||
public abstract void Set(T t);
|
||||
public override void Set<Unknow>(Unknow obj)
|
||||
{
|
||||
if (obj is T t)
|
||||
{
|
||||
Set(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
public abstract class BITAction : MonoBehaviour, IAction
|
||||
{
|
||||
public abstract void Excute();
|
||||
}
|
||||
public interface ICustomInspector
|
||||
{
|
||||
VisualElement GetVisualElement();
|
||||
}
|
||||
[System.Serializable]
|
||||
public struct FrameUpdate
|
||||
{
|
||||
float prevframe;
|
||||
bool updatedThisFrame;
|
||||
public static implicit operator bool(FrameUpdate self)
|
||||
{
|
||||
var updatedThisFrame = Utility.Time.time <= self.prevframe;
|
||||
if (updatedThisFrame)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.prevframe = Utility.Time.time;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
[System.Serializable]
|
||||
public class CompletionRate
|
||||
{
|
||||
public IntervalUpdate resetInterval = new(1);
|
||||
int requestCount;
|
||||
int successCount;
|
||||
public float rate;
|
||||
public int resetWhen = 64;
|
||||
public static implicit operator float(CompletionRate cr)
|
||||
{
|
||||
return cr.rate;
|
||||
}
|
||||
public void Get()
|
||||
{
|
||||
requestCount++;
|
||||
}
|
||||
public void Release()
|
||||
{
|
||||
successCount++;
|
||||
rate = (float)successCount / (float)requestCount;
|
||||
if (requestCount > resetWhen)
|
||||
{
|
||||
requestCount = successCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
[System.Serializable]
|
||||
public class Counter
|
||||
{
|
||||
public int count;
|
||||
int currentCount;
|
||||
public IntervalUpdate updater = new(1);
|
||||
public static implicit operator int(Counter self) => self.Get();
|
||||
public int Excute()
|
||||
{
|
||||
if (updater)
|
||||
{
|
||||
count = currentCount;
|
||||
currentCount = 0;
|
||||
}
|
||||
currentCount++;
|
||||
return count;
|
||||
}
|
||||
public int Get() => currentCount;
|
||||
}
|
||||
[System.Serializable]
|
||||
public class IntervalUpdate
|
||||
{
|
||||
public IntervalUpdate(float updateInterval = 0)
|
||||
{
|
||||
this.updateInterval = updateInterval;
|
||||
}
|
||||
public bool enable = true;
|
||||
public float updateInterval;
|
||||
private double enableUpdateTime;
|
||||
public bool canUpdate => (Utility.Time.timeAsDouble >= enableUpdateTime);
|
||||
private bool canUpdateThisFrame;
|
||||
public event Action<bool> onSetActive;
|
||||
public static implicit operator bool(IntervalUpdate value)
|
||||
{
|
||||
return value is not null && value.CanUpdate();
|
||||
}
|
||||
public static implicit operator float(IntervalUpdate value)
|
||||
{
|
||||
return value is not null ? value.updateInterval : 0;
|
||||
}
|
||||
public bool CanUpdate()
|
||||
{
|
||||
canUpdateThisFrame = canUpdate;
|
||||
if (canUpdate)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
return enable && canUpdateThisFrame;
|
||||
}
|
||||
public float GetDuration()
|
||||
{
|
||||
var duration = (float)(Utility.Time.timeAsDouble - enableUpdateTime);
|
||||
//duration = duration.Round(2);
|
||||
return duration;
|
||||
}
|
||||
public void Reset(bool immediately = false)
|
||||
{
|
||||
enableUpdateTime = Utility.Time.timeAsDouble + (immediately ? 0 : updateInterval);
|
||||
}
|
||||
public void AddDelay(float value)
|
||||
{
|
||||
Reset();
|
||||
enableUpdateTime += value;
|
||||
}
|
||||
public void SetActive(bool active)
|
||||
{
|
||||
enable = active;
|
||||
onSetActive?.Invoke(active);
|
||||
}
|
||||
}
|
||||
public struct Location
|
||||
{
|
||||
|
||||
public Location(Transform transform, bool local = false)
|
||||
{
|
||||
if (local)
|
||||
{
|
||||
position = transform.localPosition;
|
||||
rotation = transform.localRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
position = transform.position;
|
||||
rotation = transform.rotation;
|
||||
}
|
||||
|
||||
forward = transform.forward;
|
||||
}
|
||||
public Location(Component component)
|
||||
{
|
||||
var transform = component.transform;
|
||||
position = transform.position;
|
||||
rotation = transform.rotation;
|
||||
forward = transform.forward;
|
||||
}
|
||||
public Vector3 position;
|
||||
public Vector3 forward;
|
||||
public Quaternion rotation;
|
||||
public Location Set(Vector3 value)
|
||||
{
|
||||
position = value;
|
||||
return this;
|
||||
}
|
||||
public Location Set(Quaternion value)
|
||||
{
|
||||
rotation = value;
|
||||
return this;
|
||||
}
|
||||
public Location Set(Transform value, bool isLocal)
|
||||
{
|
||||
if (isLocal)
|
||||
{
|
||||
position = value.localPosition; rotation = value.localRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
Set(value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Location Set(Transform value)
|
||||
{
|
||||
position = value.position; rotation = value.rotation;
|
||||
return this;
|
||||
}
|
||||
public static Location Lerp(Location a, Location b, float t)
|
||||
{
|
||||
if (Quaternion.Dot(a, a) < Quaternion.kEpsilon)
|
||||
a.rotation = Quaternion.identity;
|
||||
if (Quaternion.Dot(b, b) < Quaternion.kEpsilon)
|
||||
b.rotation = Quaternion.identity;
|
||||
return new()
|
||||
{
|
||||
position = Vector3.Lerp(a.position, b.position, t),
|
||||
rotation = Quaternion.Lerp(a.rotation, b.rotation, t)
|
||||
};
|
||||
}
|
||||
public static implicit operator Vector3(Location self)
|
||||
{
|
||||
return self.position;
|
||||
}
|
||||
public static implicit operator Quaternion(Location self)
|
||||
{
|
||||
return self.rotation;
|
||||
}
|
||||
public static Location operator +(Location self, Location b)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
position = self.position + b.position,
|
||||
rotation = Quaternion.Euler(self.rotation.eulerAngles + b.rotation.eulerAngles),
|
||||
};
|
||||
}
|
||||
public static Location operator -(Location self, Location b)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
position = self.position - b.position,
|
||||
rotation = Quaternion.Euler(self.rotation.eulerAngles - b.rotation.eulerAngles),
|
||||
};
|
||||
}
|
||||
public static Location operator *(Location self, float weight)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
position = self.position * weight,
|
||||
rotation = Quaternion.Euler(self.rotation.eulerAngles * weight),
|
||||
};
|
||||
}
|
||||
public static Location operator /(Location self, float weight)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
position = self.position / weight,
|
||||
rotation = Quaternion.Euler(self.rotation.eulerAngles / weight),
|
||||
};
|
||||
}
|
||||
public bool isNull
|
||||
{
|
||||
get
|
||||
{
|
||||
return position == Vector3.zero && rotation == Quaternion.identity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
Unity/Scripts/Utility/UtilityHelper.cs
Normal file
15
Unity/Scripts/Utility/UtilityHelper.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
namespace BITKit
|
||||
{
|
||||
public static class UtilityHelper
|
||||
{
|
||||
public static bool isPlaying => BehaviourHelper.Actived;
|
||||
public static bool isValid => BehaviourHelper.Actived;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user