Compare commits
6 Commits
223df3fb91
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fd68071416 | |||
| a530eba460 | |||
| 32f0038e34 | |||
| c12d4a3754 | |||
| a3483f23d8 | |||
| 3db8bde1c2 |
@@ -8,12 +8,15 @@ using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Convention.WindowsUI;
|
||||
using Demo.Game;
|
||||
using Unity.Collections;
|
||||
using UnityEditor;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.Build;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
@@ -1271,7 +1274,11 @@ namespace Convention
|
||||
#endif
|
||||
public static void InitExtensionEnv()
|
||||
{
|
||||
UnityEngine.Application.quitting += () => CoroutineStarter = null;
|
||||
UnityEngine.Application.quitting += () =>
|
||||
{
|
||||
GameObject.Destroy(s_CoroutineStarter.gameObject);
|
||||
s_CoroutineStarter = null;
|
||||
};
|
||||
|
||||
InitExtensionEnvCalls();
|
||||
GlobalConfig.InitExtensionEnv();
|
||||
@@ -1285,27 +1292,82 @@ namespace Convention
|
||||
return MainThreadID == Thread.CurrentThread.ManagedThreadId;
|
||||
}
|
||||
|
||||
private static CoroutineMonoStarterUtil CoroutineStarter;
|
||||
private static CoroutineMonoStarterUtil s_CoroutineStarter;
|
||||
private static CoroutineMonoStarterUtil CoroutineStarter
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_CoroutineStarter == null)
|
||||
{
|
||||
s_CoroutineStarter = new GameObject($"{nameof(ConventionUtility)}-{nameof(CoroutineStarter)}").AddComponent<CoroutineMonoStarterUtil>();
|
||||
}
|
||||
return s_CoroutineStarter;
|
||||
}
|
||||
}
|
||||
|
||||
public static GameObject Singleton => CoroutineStarter.gameObject;
|
||||
|
||||
private class CoroutineMonoStarterUtil : MonoBehaviour
|
||||
{
|
||||
internal float waitClock;
|
||||
private void Update()
|
||||
{
|
||||
waitClock = Time.realtimeSinceStartup;
|
||||
MainThreadID = Thread.CurrentThread.ManagedThreadId;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
CoroutineStarter = null;
|
||||
s_CoroutineStarter = null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 包装即将用于协程的迭代器成为一个防止假死机的迭代器
|
||||
/// </summary>
|
||||
/// <param name="ir"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerator AvoidFakeStop(IEnumerator ir, float fps = 5)
|
||||
{
|
||||
Stack<IEnumerator> loadingTask = new();
|
||||
loadingTask.Push(ir);
|
||||
float maxWaitClock = 1 / fps;
|
||||
while (loadingTask.Count > 0)
|
||||
{
|
||||
// 防止大量无延迟函数的使用导致假死机
|
||||
//if (Time.realtimeSinceStartup - CoroutineStarter.waitClock > maxWaitClock)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
if (loadingTask.Peek().MoveNext())
|
||||
{
|
||||
if (loadingTask.Peek().Current is IEnumerator next)
|
||||
loadingTask.Push(next);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadingTask.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 包装即将用于协程的迭代器成为一个防止假死机的迭代器
|
||||
/// </summary>
|
||||
/// <param name="ir"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerator AvoidFakeStopWithoutDeepStack(IEnumerator ir, float fps = 5)
|
||||
{
|
||||
float maxWaitClock = 1 / fps;
|
||||
while (ir.MoveNext())
|
||||
{
|
||||
// 防止大量无延迟函数的使用导致假死机
|
||||
if (Time.realtimeSinceStartup - CoroutineStarter.waitClock > maxWaitClock)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static Coroutine StartCoroutine(IEnumerator coroutine)
|
||||
{
|
||||
if (CoroutineStarter == null)
|
||||
{
|
||||
CoroutineStarter = new GameObject($"{nameof(ConventionUtility)}-{nameof(CoroutineStarter)}").AddComponent<CoroutineMonoStarterUtil>();
|
||||
}
|
||||
return CoroutineStarter.StartCoroutine(coroutine);
|
||||
}
|
||||
public static void CloseCoroutine(Coroutine coroutine)
|
||||
@@ -2539,3 +2601,441 @@ namespace Convention
|
||||
}
|
||||
}
|
||||
|
||||
namespace Convention
|
||||
{
|
||||
public static class BinarySerializeUtility
|
||||
{
|
||||
#region Base
|
||||
|
||||
public static void WriteBool(BinaryWriter writer, bool data)
|
||||
{
|
||||
writer.Write(data);
|
||||
}
|
||||
public static bool ReadBool(BinaryReader reader)
|
||||
{
|
||||
return reader.ReadBoolean();
|
||||
}
|
||||
public static void WriteInt(BinaryWriter writer, in int data)
|
||||
{
|
||||
writer.Write(data);
|
||||
}
|
||||
public static int ReadInt(BinaryReader reader)
|
||||
{
|
||||
return reader.ReadInt32();
|
||||
}
|
||||
public static void WriteFloat(BinaryWriter writer, in float data)
|
||||
{
|
||||
writer.Write(data);
|
||||
}
|
||||
public static float ReadFloat(BinaryReader reader)
|
||||
{
|
||||
return reader.ReadSingle();
|
||||
}
|
||||
public static void WriteChar(BinaryWriter writer, in char data)
|
||||
{
|
||||
writer.Write(data);
|
||||
}
|
||||
public static char ReadChar(BinaryReader reader)
|
||||
{
|
||||
return reader.ReadChar();
|
||||
}
|
||||
public static void WriteString(BinaryWriter writer, in string data)
|
||||
{
|
||||
writer.Write(data ?? "");
|
||||
}
|
||||
public static string ReadString(BinaryReader reader)
|
||||
{
|
||||
return reader.ReadString();
|
||||
}
|
||||
public static void WriteVec3(BinaryWriter writer, in Vector3 data)
|
||||
{
|
||||
writer.Write(data.x);
|
||||
writer.Write(data.y);
|
||||
writer.Write(data.z);
|
||||
}
|
||||
public static Vector3 ReadVec3(BinaryReader reader)
|
||||
{
|
||||
float x, y, z;
|
||||
x = reader.ReadSingle();
|
||||
y = reader.ReadSingle();
|
||||
z = reader.ReadSingle();
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
public static void WriteVec2(BinaryWriter writer, in Vector2 data)
|
||||
{
|
||||
writer.Write(data.x);
|
||||
writer.Write(data.y);
|
||||
}
|
||||
public static Vector2 ReadVec2(BinaryReader reader)
|
||||
{
|
||||
float x, y;
|
||||
x = reader.ReadSingle();
|
||||
y = reader.ReadSingle();
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
public static void WriteColor(BinaryWriter writer, in Color data)
|
||||
{
|
||||
writer.Write(data.r);
|
||||
writer.Write(data.g);
|
||||
writer.Write(data.b);
|
||||
writer.Write(data.a);
|
||||
}
|
||||
public static Color ReadColor(BinaryReader reader)
|
||||
{
|
||||
float r, g, b, a;
|
||||
r = reader.ReadSingle();
|
||||
g = reader.ReadSingle();
|
||||
b = reader.ReadSingle();
|
||||
a = reader.ReadSingle();
|
||||
return new(r, g, b, a);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Serialize
|
||||
|
||||
#region Int
|
||||
|
||||
public static void SerializeNativeArray(BinaryWriter writer, in NativeArray<int> array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start++]);
|
||||
}
|
||||
}
|
||||
public static int DeserializeNativeArray(BinaryReader reader, ref NativeArray<int> array)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
if (array.Length < count)
|
||||
array.ResizeArray(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[i] = reader.ReadInt32();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public static void SerializeArray(BinaryWriter writer, in int[] array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start++]);
|
||||
}
|
||||
}
|
||||
public static int[] DeserializeIntArray(BinaryReader reader)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
int[] array = new int[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[i] = reader.ReadInt32();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Float
|
||||
|
||||
public static void SerializeNativeArray(BinaryWriter writer, in NativeArray<float> array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start++]);
|
||||
}
|
||||
}
|
||||
public static int DeserializeNativeArray(BinaryReader reader, ref NativeArray<float> array)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
if (array.Length < count)
|
||||
array.ResizeArray(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[i] = reader.ReadSingle();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public static void SerializeArray(BinaryWriter writer, in float[] array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start++]);
|
||||
}
|
||||
}
|
||||
public static float[] DeserializeFloatArray(BinaryReader reader)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
float[] array = new float[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[i] = reader.ReadSingle();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region String
|
||||
|
||||
public static void SerializeArray(BinaryWriter writer, in string[] array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start++] ?? "");
|
||||
}
|
||||
}
|
||||
public static string[] DeserializeStringArray(BinaryReader reader)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
string[] array = new string[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[i] = reader.ReadString();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Vector3
|
||||
|
||||
public static void SerializeNativeArray(BinaryWriter writer, in NativeArray<Vector3> array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start].x);
|
||||
writer.Write(array[start].y);
|
||||
writer.Write(array[start].z);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
public static int DeserializeNativeArray(BinaryReader reader, ref NativeArray<Vector3> array)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
if (array.Length < count)
|
||||
array.ResizeArray(count);
|
||||
float x, y, z;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
x = reader.ReadSingle();
|
||||
y = reader.ReadSingle();
|
||||
z = reader.ReadSingle();
|
||||
array[i] = new(x, y, z);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public static void SerializeArray(BinaryWriter writer, in Vector3[] array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start].x);
|
||||
writer.Write(array[start].y);
|
||||
writer.Write(array[start].z);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
public static Vector3[] DeserializeVec3Array(BinaryReader reader, int start = 0)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
Vector3[] array = new Vector3[count];
|
||||
float x, y, z;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
x = reader.ReadSingle();
|
||||
y = reader.ReadSingle();
|
||||
z = reader.ReadSingle();
|
||||
array[start + i] = new(x, y, z);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Vector2
|
||||
|
||||
public static void SerializeNativeArray(BinaryWriter writer, in NativeArray<Vector2> array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start].x);
|
||||
writer.Write(array[start].y);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
public static int DeserializeNativeArray(BinaryReader reader, ref NativeArray<Vector2> array)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
if (array.Length < count)
|
||||
array.ResizeArray(count);
|
||||
float x, y;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
x = reader.ReadSingle();
|
||||
y = reader.ReadSingle();
|
||||
array[i] = new(x, y);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public static void SerializeArray(BinaryWriter writer, in Vector2[] array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
writer.Write(array[start].x);
|
||||
writer.Write(array[start].y);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
public static Vector2[] DeserializeVec2Array(BinaryReader reader)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
Vector2[] array = new Vector2[count];
|
||||
float x, y;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
x = reader.ReadSingle();
|
||||
y = reader.ReadSingle();
|
||||
array[i] = new(x, y);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Color
|
||||
|
||||
public static void SerializeNativeArray(BinaryWriter writer, in NativeArray<Color> array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
WriteColor(writer, array[start]);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
public static int DeserializeNativeArray(BinaryReader reader, ref NativeArray<Color> array)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
if (array.Length < count)
|
||||
array.ResizeArray(count);
|
||||
float x, y, z;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[i] = ReadColor(reader);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public static void SerializeArray(BinaryWriter writer, in Color[] array, int start = 0, int end = int.MaxValue)
|
||||
{
|
||||
int e = Mathf.Min(array.Length, end);
|
||||
writer.Write(e - start);
|
||||
while (start < e)
|
||||
{
|
||||
WriteColor(writer, array[start]);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
public static Color[] DeserializeVec3Array(BinaryReader reader)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
Color[] array = new Color[count];
|
||||
float x, y, z;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[i] = ReadColor(reader);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static partial class Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取类型的友好显示名称,支持泛型、数组等复杂类型
|
||||
/// </summary>
|
||||
public static string GetFriendlyName(this Type type)
|
||||
{
|
||||
if (type == null) return null;
|
||||
|
||||
// 处理泛型类型
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
// 特殊处理可空类型(Nullable<T>)
|
||||
if (type.IsNullable())
|
||||
{
|
||||
return $"{GetFriendlyName(type.GetGenericArguments()[0])}?";
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
// 获取类型基础名称(移除 `1, `2 等后缀)
|
||||
string baseName = type.Name.Contains('`') ? type.Name[..type.Name.IndexOf('`')] : type.Name;
|
||||
sb.Append(baseName);
|
||||
sb.Append('<');
|
||||
|
||||
// 递归处理泛型参数
|
||||
Type[] args = type.GetGenericArguments();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if (i > 0) sb.Append(", ");
|
||||
sb.Append(GetFriendlyName(args[i]));
|
||||
}
|
||||
|
||||
sb.Append('>');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
// 处理数组类型
|
||||
if (type.IsArray)
|
||||
{
|
||||
string elementName = GetFriendlyName(type.GetElementType());
|
||||
int rank = type.GetArrayRank();
|
||||
return rank == 1 ? $"{elementName}[]" : $"{elementName}[{new string(',', rank - 1)}]";
|
||||
}
|
||||
|
||||
// 处理指针类型
|
||||
if (type.IsPointer)
|
||||
{
|
||||
return $"{GetFriendlyName(type.GetElementType())}*";
|
||||
}
|
||||
|
||||
// 处理引用类型(ref/out 参数)
|
||||
if (type.IsByRef)
|
||||
{
|
||||
return $"{GetFriendlyName(type.GetElementType())}&";
|
||||
}
|
||||
|
||||
// 普通类型直接返回名称
|
||||
return type.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否为可空类型
|
||||
/// </summary>
|
||||
public static bool IsNullable(this Type type)
|
||||
{
|
||||
return type.IsGenericType &&
|
||||
type.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user