初始化

This commit is contained in:
come
2025-07-26 16:56:42 +08:00
parent 8291dbb91c
commit fa81439a8c
2574 changed files with 328492 additions and 2170 deletions

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace YIUIFramework
{
public static class AppDomainExt
{
/// <summary>
/// 得到对应Assembly名字内所有type的集合
/// 例: GetTypesByDllName("Framework")
/// </summary>
/// <param name="owner"></param>
/// <param name="names"></param>
/// <returns></returns>
public static Type[] GetTypesByAssemblyName(this AppDomain owner, params string[] names)
{
if (names.Length < 1)
{
return Array.Empty<Type>();
}
var nameMap = new Dictionary<string, bool>(names.Length);
foreach (string assemblyName in names)
{
nameMap[assemblyName] = true;
}
List<Type> allType = new List<Type>();
Assembly[] assemblyArr = owner.GetAssemblies();
foreach (Assembly assembly in assemblyArr)
{
if (!nameMap.ContainsKey(assembly.GetName().Name))
{
continue;
}
allType.AddRange(assembly.GetTypes());
}
return allType.ToArray();
}
/// <summary>
/// 得到一个域下的所有实现interfaceType的类型
/// </summary>
/// <param name="owner"></param>
/// <param name="interfaceType"></param>
/// <returns></returns>
public static Type[] GetTypesByInterface(this AppDomain owner, Type interfaceType)
{
return AppDomain.CurrentDomain.GetAssemblies().SelectMany(a =>
{
return a.GetTypes()
.Where(t => t.GetInterfaces()
.Contains(interfaceType));
}).ToArray();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ef0dd73e8d4e44f28b9cc9478fa34c84
timeCreated: 1681720464

View File

@@ -0,0 +1,56 @@
using System;
namespace YIUIFramework
{
public partial class AppTick
{
private static readonly AppTick g_inst = new AppTick();
public static int Count
{
get { return g_inst.Get(); }
}
}
/// <summary>
/// 为了解决系统的TickCount时间不足问题
/// 这个Tick是从第一次调用开始计数
/// 注意,为了性能,所以没有加锁
/// 所以线程不安全
/// </summary>
public partial class AppTick
{
private int m_lastTick;
private int m_count;
public AppTick()
{
m_lastTick = Environment.TickCount;
}
/// <summary>
/// 单位是MS
/// 可以支撑程序跑24.9天不翻转
/// 如果他真的一直开着应用24天我认了
/// 这里不把单位定成uint,以让他支持48天
/// 是因为多了代码转换考虑到24天已经足够用
/// 并且这个方法是会频繁调用,所以越简单越好
/// </summary>
public int Get()
{
int cur = Environment.TickCount;
if (cur < m_lastTick)
{
m_count += int.MaxValue - m_lastTick;
m_count += cur - int.MinValue;
}
else
{
m_count += cur - m_lastTick;
}
m_lastTick = cur;
return m_count;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1453d57101cb4929863b7d503c949455
timeCreated: 1681720464

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Logger = YIUIFramework.Logger;
namespace YIUIFramework
{
/// <summary>
/// 用于只等待一次的延迟计时器。
/// </summary>
public sealed class DelayTimer : IDisposable
{
private LinkedListNode<Action> updateHandle;
private float delayTime;
private float leftTime;
private Action task;
/// <summary>
/// 在指定秒后调用任务
/// </summary>
/// <param name="delay">调用任务的时间</param>
/// <param name="task">要执行的任务</param>
public static DelayTimer Delay(float delay, Action task)
{
var timer = new DelayTimer();
timer.delayTime = delay;
timer.task = task;
timer.Start();
return timer;
}
public void Dispose()
{
SchedulerMgr.RemoveFrameListener(this.updateHandle);
this.updateHandle = null;
}
private void Start()
{
this.leftTime = this.delayTime;
this.updateHandle = SchedulerMgr.AddFrameListener(this.Update);
}
private void Update()
{
this.leftTime -= Time.deltaTime;
if (this.leftTime <= 0.0f)
{
try
{
this.task?.Invoke();
}
catch (Exception e)
{
Logger.LogError(e);
}
finally
{
this.Dispose();
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a2ee27bc48f44dfd8a3680237a22a5ac
timeCreated: 1679041382

View File

@@ -0,0 +1,23 @@
namespace YIUIFramework
{
/// <summary>
/// 静态获取对应空值的类型
/// </summary>
public static class EmptyValue<T> where T : new()
{
private static T g_value;
public static T Value
{
get
{
if (g_value == null)
{
g_value = new T();
}
return g_value;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7a26fef3d4284b65a557593f6cf42db9
timeCreated: 1681720464

View File

@@ -0,0 +1,50 @@
namespace YIUIFramework
{
/// <summary>
/// The utility class help for CPU endian transform.
/// </summary>
public static class Endian
{
/// <summary>
/// Reverse the bytes order (16-bit).
/// </summary>
/// <param name="value">The value wait for reverse.</param>
/// <returns>The reversed byte.</returns>
public static ushort ReverseBytes(ushort value)
{
return (ushort)((value & 0xFFU) << 8 | (value & 0xFF00U) >> 8);
}
/// <summary>
/// Reverse the bytes order (32-bit).
/// </summary>
/// <param name="value">The value wait for reverse.</param>
/// <returns>The reversed byte.</returns>
public static uint ReverseBytes(uint value)
{
return
(value & 0x000000FFU) << 24 |
(value & 0x0000FF00U) << 8 |
(value & 0x00FF0000U) >> 8 |
(value & 0xFF000000U) >> 24;
}
/// <summary>
/// Reverse the bytes order (64-bit).
/// </summary>
/// <param name="value">The value wait for reverse.</param>
/// <returns>The reversed byte.</returns>
public static ulong ReverseBytes(ulong value)
{
return
(value & 0x00000000000000FFUL) << 56 |
(value & 0x000000000000FF00UL) << 40 |
(value & 0x0000000000FF0000UL) << 24 |
(value & 0x00000000FF000000UL) << 8 |
(value & 0x000000FF00000000UL) >> 8 |
(value & 0x0000FF0000000000UL) >> 24 |
(value & 0x00FF000000000000UL) >> 40 |
(value & 0xFF00000000000000UL) >> 56;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e4d0485b01714b68a2ea7f4246fcf87b
timeCreated: 1679041382

View File

@@ -0,0 +1,56 @@
using System;
using System.Reflection;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 支持光线投射与网格。
/// </summary>
public static class GeometryUtilityHelper
{
private static readonly Action<Plane[], Matrix4x4>
ExtractPlanesDelegate;
static GeometryUtilityHelper()
{
var methodInfo = typeof(GeometryUtility).GetMethod(
"Internal_ExtractPlanes",
BindingFlags.NonPublic | BindingFlags.Static);
if (methodInfo != null)
{
ExtractPlanesDelegate = (Action<Plane[], Matrix4x4>)
Delegate.CreateDelegate(
typeof(Action<Plane[], Matrix4x4>),
methodInfo,
false);
}
}
/// <summary>
/// Extract the planes.
/// </summary>
public static void ExtractPlanes(Plane[] planes, Camera camera)
{
var mat = camera.projectionMatrix * camera.worldToCameraMatrix;
ExtractPlanes(planes, mat);
}
/// <summary>
/// Extract the planes.
/// </summary>
public static void ExtractPlanes(
Plane[] planes, Matrix4x4 worldToProjectionMatrix)
{
if (ExtractPlanesDelegate != null)
{
ExtractPlanesDelegate(planes, worldToProjectionMatrix);
}
else
{
GeometryUtility.CalculateFrustumPlanes(
worldToProjectionMatrix, planes);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2bdab850f1354f8f84a0819bc2df880c
timeCreated: 1679041383

View File

@@ -0,0 +1,10 @@
namespace YIUIFramework
{
/// <summary>
/// 时间提供器
/// </summary>
public interface ITimeProvider
{
int Time { get; }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a047931866164c1bae6cda0c00bcb292
timeCreated: 1681720464

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Linq;
namespace YIUIFramework
{
/// <summary>
/// The list comparer.
/// </summary>
public sealed class ListComparer<T> : IEqualityComparer<List<T>>
{
private static volatile ListComparer<T> defaultComparer;
/// <summary>
/// Gets a default instance of the <see cref="ListComparer{T}"/>.
/// </summary>
public static ListComparer<T> Default
{
get
{
if (defaultComparer == null)
{
defaultComparer = new ListComparer<T>();
}
return defaultComparer;
}
}
/// <inheritdoc />
public bool Equals(List<T> x, List<T> y)
{
return x.SequenceEqual(y);
}
/// <inheritdoc />
public int GetHashCode(List<T> obj)
{
int hashcode = 0;
foreach (T t in obj)
{
hashcode ^= t.GetHashCode();
}
return hashcode;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 73cedaab2e584912b039630ae9e446a5
timeCreated: 1679041382

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c11e918a1c5c44069ae4bfef8ea9b007
timeCreated: 1711881986

View File

@@ -0,0 +1,43 @@
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
namespace YIUIFramework
{
public class AsyncLockComponent : IDisposable, IRefPool
{
private readonly SemaphoreSlim m_Semaphore = new SemaphoreSlim(1, 1);
private long m_Key;
private int m_MillisecondsTimeout;
public AsyncLockComponent()
{
}
public void Reset(long key, int millisecondsTimeout = -1)
{
m_Key = key;
m_MillisecondsTimeout = millisecondsTimeout;
}
public async UniTask<AsyncLockComponent> WaitAsync()
{
await m_Semaphore.WaitAsync(m_MillisecondsTimeout);
return this;
}
public void Dispose()
{
m_Semaphore.Release();
if (AsyncLockMgr.Inst.Release(m_Key))
{
RefPool.Put(this);
}
}
public void Recycle()
{
Reset(0);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4226913148a64fc7adae38e6959e43d4
timeCreated: 1711882006

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
namespace YIUIFramework
{
//小型异步锁
public class AsyncLockMgr : MgrSingleton<AsyncLockMgr>
{
private readonly Dictionary<long, AsyncLockComponent> m_SemaphoreSlims = new Dictionary<long, AsyncLockComponent>();
private readonly Dictionary<long, int> m_SemaphoreSlimsRefCount = new Dictionary<long, int>();
internal bool Release(long key)
{
if (m_SemaphoreSlimsRefCount.ContainsKey(key))
{
m_SemaphoreSlimsRefCount[key] -= 1;
if (m_SemaphoreSlimsRefCount[key] <= 0)
{
m_SemaphoreSlimsRefCount.Remove(key);
m_SemaphoreSlims.Remove(key);
return true;
}
}
return false;
}
//这就是一个小型的异步锁
//不考虑其他非常丰富的功能
//只能锁定一个key 注意一个对象你要同时开多个不同类型锁时 需要用不同的key
//推荐使用GetHashCode做Key 但是一个对象只能同时一个
public async UniTask<AsyncLockComponent> Wait(long key, int millisecondsTimeout = -1)
{
if (!m_SemaphoreSlims.TryGetValue(key, out var semaphoreSlimComponent))
{
semaphoreSlimComponent = RefPool.Get<AsyncLockComponent>();
semaphoreSlimComponent.Reset(key, millisecondsTimeout);
m_SemaphoreSlims.Add(key, semaphoreSlimComponent);
m_SemaphoreSlimsRefCount.Add(key, 0);
}
m_SemaphoreSlimsRefCount[key] += 1;
return await semaphoreSlimComponent.WaitAsync();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 636fdaac7f9b459589ab71a928d0e0d7
timeCreated: 1711882006

View File

@@ -0,0 +1,209 @@
using System;
namespace YIUIFramework
{
public class MathUtil
{
private static double PrecisionIntercept(double input)
{
return (int)(input * 1000.0) / 1000.0;
}
public const double PI = (int)(Math.PI * 1000.0) / 1000.0;
/// <summary>
/// 2 * pi
/// </summary>
public const double PI2 = PI * 2f;
/// <summary>
/// 弧度转角度
/// </summary>
public const double R2A = 180 / PI;
/// <summary>
/// 角度转弧度
/// </summary>
public const double A2R = PI / 180;
/// <summary>
/// 跟号2
/// </summary>
public static double Sqrt2 = Math.Sqrt(2);
public static float Clamp(float value, float max, float min)
{
if (value < min)
{
value = min;
}
if (value > max)
{
value = max;
}
return value;
}
public static int Clamp(int value, int max, int min)
{
if (value < min)
{
value = min;
}
if (value > max)
{
value = max;
}
return value;
}
public static float DistanceNoSqrt(float ax, float ay, float bx, float by)
{
float dx = ax - bx;
float dy = ay - by;
return dx * dx + dy * dy;
}
public static float Distance(float ax, float ay, float bx, float by)
{
float dx = ax - bx;
float dy = ay - by;
return (float)PrecisionIntercept(Math.Sqrt(dx * dx + dy * dy));
}
public static double DistanceTo(double ax, double ay, double bx, double by)
{
double dx = ax - bx;
double dy = ay - by;
return PrecisionIntercept(Math.Sqrt(dx * dx + dy * dy));
}
public static int DistanceTo(int ax, int ay, int bx, int by)
{
int dx = ax - bx;
int dy = ay - by;
return (int)Math.Sqrt(dx * dx + dy * dy);
}
public static int CalcuIndexByXY(int x, int y, int width)
{
return y * width + x;
}
public static float Fract(float x)
{
return x - (int)PrecisionIntercept(Math.Floor(x));
}
/// <summary>
/// 判断值是否在min and max之间包含min and max
/// </summary>
/// <param name="value"></param>
/// <param name="min"></param>
/// <param name="max"></param>
/// <returns></returns>
public static bool IsRange(int value, int min, int max)
{
return !(value < min || value > max);
}
public static bool Range(ref float value, float min, float max)
{
if (value < min)
{
value = min;
return true;
}
else if (value > max)
{
value = max;
return true;
}
return false;
}
public static bool Range(ref int value, int min, int max)
{
if (value < min)
{
value = min;
return true;
}
else if (value > max)
{
value = max;
return true;
}
return false;
}
public static bool Range(ref double value, double min, double max)
{
if (value < min)
{
value = min;
return true;
}
else if (value > max)
{
value = max;
return true;
}
return false;
}
public static int FixedByRange(int value, int min, int max)
{
Range(ref value, min, max);
return value;
}
public static float FixedByRange(float value, float min, float max)
{
Range(ref value, min, max);
return value;
}
public static double Sqrt(double d)
{
return PrecisionIntercept(Math.Sqrt(d));
}
public static double Floor(double d)
{
return PrecisionIntercept(Math.Floor(d));
}
public static double Atan2(double y, double x)
{
return PrecisionIntercept(Math.Atan2(y, x));
}
public static double Sin(double a)
{
return PrecisionIntercept(Math.Sin(a));
}
public static double Cos(double d)
{
return PrecisionIntercept(Math.Cos(d));
}
public static double Pow(double x, double y)
{
return PrecisionIntercept(Math.Pow(x, y));
}
public static double Ceiling(double d)
{
return PrecisionIntercept(Math.Ceiling(d));
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 09088f53364b4d99b9c4801b19323dec
timeCreated: 1681720464

View File

@@ -0,0 +1,129 @@
using System.Text.RegularExpressions;
using Logger = YIUIFramework.Logger;
namespace YIUIFramework
{
public static class NameUtility
{
//统一命名
public const string FirstName = "u_"; //不使用m_ 这个是给具体逻辑用的 u_ 就知道这个是自动创建的 也避免命名冲突
public const string ComponentName = "Com";
public const string DataName = "Data";
public const string EventName = "Event";
public const string UIName = "UI";
//名字只允许以下的正则表达式
public const string NameRegex = "[^a-z0-9A-Z_]";
//m_必须大写
public const bool Big = true;
public static bool CheckFirstName(this string name, string otherName)
{
return !string.IsNullOrEmpty(name) && name.StartsWith($"{FirstName}{otherName}");
}
public static bool CheckComponentName(this string name)
{
return !string.IsNullOrEmpty(name) && name.StartsWith($"{FirstName}{ComponentName}");
}
public static bool CheckDataName(this string name)
{
return !string.IsNullOrEmpty(name) && name.StartsWith($"{FirstName}{DataName}");
}
public static bool CheckEventName(this string name)
{
return !string.IsNullOrEmpty(name) && name.StartsWith($"{FirstName}{EventName}");
}
public static bool CheckUIName(this string name)
{
return !string.IsNullOrEmpty(name) && name.StartsWith($"{FirstName}{UIName}");
}
/// <summary>
/// 必须满足m_
/// 然后吧目标第3个字母改为大写
/// 返回改变后的字符串 如果相同就没有修改
/// 如果不同就是被修改了
/// </summary>
public static string ChangeToBigName(this string name, string otherName)
{
if (!Big)
{
return name;
}
if (string.IsNullOrEmpty(name))
{
Logger.LogError($"名字是空的 无法判断 请检查");
return name;
}
if (!CheckFirstName(name, otherName))
{
Logger.LogError($"当前命名 不符合 {FirstName}{otherName} 规范 无法检查是否大写");
return name;
}
var minLength = FirstName.Length + otherName.Length;
return ToUpperByIndex(name, (uint)minLength);
}
public static string ToFirstUpper(string name)
{
return ToUpperByIndex(name, 0);
}
public static string GetQualifiedName(string name)
{
if (name.IndexOf("(Clone)") > -1)
{
name = name.Replace("(Clone)", string.Empty);
}
name = Regex.Replace(name, NameRegex, ""); //替换所有非法字符
return name;
}
public static string ToUpperByIndex(string name, uint index)
{
if (string.IsNullOrEmpty(name))
{
Logger.LogError($"名字是空的 无法判断 请检查");
return name;
}
name = GetQualifiedName(name);
var arrayName = name.ToCharArray();
if (arrayName.Length <= index)
{
Logger.LogError($"替换后名称长度不符 {name} 长度:{arrayName.Length} < {index}");
return name;
}
var charUpper = arrayName[index];
if (charUpper >= 'A' && charUpper <= 'Z')
{
return name;
}
if (charUpper >= 'a' && charUpper <= 'z')
{
var charTo = charUpper.ToString().ToUpper().ToCharArray();
arrayName[index] = charTo[0];
}
else
{
arrayName[index] = 'A';
}
return new string(arrayName);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e34ce0c6ec3b422aa4cfdc83b9624e23
timeCreated: 1679038898

View File

@@ -0,0 +1,28 @@
namespace YIUIFramework
{
public static class NumChecker
{
public static bool CheckRange(ref float value, float min, float max)
{
if (value < min)
{
value = min;
return false;
}
if (value > max)
{
value = max;
return false;
}
return true;
}
public static float GetRange(float value, float min, float max)
{
CheckRange(ref value, min, max);
return value;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1ebb4a95b51e494bbaac09bc72041a78
timeCreated: 1681720464

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections;
namespace YIUIFramework
{
public class ParamVo
{
private static readonly SimplePool<ParamVo> g_cacheParam = new SimplePool<ParamVo>(5);
/// <summary>
/// 原始数据
/// </summary>
public object Data;
public ParamVo()
{
}
public ParamVo(object data)
{
Data = data;
}
public T Get<T>(int index = 0, T defaultValue = default(T))
{
T result;
Get(out result, index, defaultValue);
return result;
}
/// <summary>
/// 取出参数列表的第index个
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="outResult"></param>
/// <param name="index"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public ParamGetResult Get<T>(out T outResult, int index = 0, T defaultValue = default(T))
{
if (Data == null)
{
outResult = defaultValue;
return ParamGetResult.DataIsNull;
}
if (index < 0)
{
outResult = defaultValue;
return ParamGetResult.IndexIsLess;
}
object data;
if (Data is IList)
{
IList datas = (IList)Data;
if (index >= datas.Count)
{
outResult = defaultValue;
return ParamGetResult.IndexIsOut;
}
data = datas[index];
}
else
{
if (index != 0)
{
outResult = defaultValue;
return ParamGetResult.IndexIsOut;
}
data = Data;
}
//如果数据是字符串,并且相要的值是数值类型,则自动转换
if (data is string && typeof(T).IsNumericType())
{
if (StrConv.ToNumber<T>((string)data, out outResult))
{
return ParamGetResult.Success;
}
outResult = defaultValue;
return ParamGetResult.ParseErr;
}
try
{
outResult = (T)data;
return ParamGetResult.Success;
}
catch (Exception)
{
outResult = defaultValue;
return ParamGetResult.ParseErr;
}
}
public void Reset()
{
Data = null;
}
public static ParamVo Get(object data = null)
{
ParamVo paramVo = g_cacheParam.Get();
paramVo.Data = data;
return paramVo;
}
public static void Put(ParamVo value)
{
if (value != null)
{
value.Data = null;
g_cacheParam.Put(value);
}
}
}
public enum ParamGetResult
{
Success,
DataIsNull,
IndexIsLess,
IndexIsOut,
ParseErr
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: df84c9ab5e8d4ac39604ff9a37e31742
timeCreated: 1681720464

View File

@@ -0,0 +1,410 @@
using System;
using UnityEngine;
namespace YIUIFramework
{
/// 用于本地小数据量记录的playerPre的包装用于方便把单个设置项直接当做变量使用
/// 使用这个可以避免读取时每次都调用PlayerPrefs
/// 另外集成了以groupKey(比如userid)来分组数据
public struct Prefs<T>
{
private T m_value;
private string m_key;
private string m_valueKey;
private RwFlag m_rwFlag;
private int m_groupKeyVer;
private IGroupKey m_groupKey;
private IPrefsAccessor m_accessor;
private T m_defValue;
public Prefs(string key, IGroupKey groupKey, T defValue, IPrefsAccessor accessor)
{
m_defValue = defValue;
m_value = defValue;
m_groupKey = groupKey;
m_accessor = accessor;
m_groupKeyVer = int.MinValue;
m_rwFlag = RwFlag.None;
m_valueKey = key;
m_key = key;
UpdateKey();
}
private void UpdateKey(bool notWrite = false)
{
if (m_groupKey == null)
{
return;
}
var curVer = m_groupKey.Version;
if (curVer != m_groupKeyVer)
{
m_groupKeyVer = curVer;
var oldKey = m_key;
m_key = StrUtil.Concat(m_groupKey.Key, "|", m_valueKey);
if (m_rwFlag.Has(RwFlag.Write))
{
if (oldKey != m_key)
{
//如果之前已经有写入,则需要删除旧的,写入新的
PlayerPrefs.DeleteKey(oldKey);
if (!notWrite)
{
m_accessor.Set(m_key, m_value);
}
}
}
//清除读取标记
m_rwFlag.UnmarkSelf(RwFlag.Read);
}
}
public T Value
{
get
{
UpdateKey();
//如果即没有读过,也没有写过
if (!m_rwFlag.Overlaps(RwFlag.Full))
{
if (m_accessor.HasKey(m_key))
{
m_value = m_accessor.Get(m_key);
}
else if (m_groupKey != null && m_accessor.HasKey(m_valueKey))
{
//第一次时,如果定向的值拿不到,就去尝试拿全局的值
m_value = m_accessor.Get(m_valueKey);
}
else
{
m_value = m_defValue;
}
m_rwFlag.MarkSelf(RwFlag.Read);
}
return m_value;
}
set
{
UpdateKey();
if (m_rwFlag.Overlaps(RwFlag.Full) && value.Equals(m_value))
{
return;
}
m_value = value;
m_rwFlag |= RwFlag.Write;
m_accessor.Set(m_key, value);
}
}
public void Delete()
{
UpdateKey(true);
m_groupKeyVer = int.MinValue;
m_value = default;
m_rwFlag.MarkSelf(RwFlag.Write);
PlayerPrefs.DeleteKey(m_key);
}
public interface IPrefsAccessor
{
bool HasKey(string key);
T Get(string key);
void Set(string key, T value);
}
}
public struct IntPrefs
{
private Prefs<int> m_value;
public int Value
{
get => m_value.Value;
set => m_value.Value = value;
}
public IntPrefs(string key, IGroupKey groupKey = null, int defValue = 0)
{
m_value = new Prefs<int>(key, groupKey, defValue, IntAccessor.Inst);
}
public void Delete()
{
m_value.Delete();
}
public static implicit operator int(IntPrefs value)
{
return value.Value;
}
}
public struct FloatPrefs
{
private Prefs<float> m_value;
public float Value
{
get => m_value.Value;
set => m_value.Value = value;
}
public FloatPrefs(string key, IGroupKey groupKey = null, float defValue = 0f)
{
m_value = new Prefs<float>(key, groupKey, defValue, FloatAccessor.Inst);
}
public void Delete()
{
m_value.Delete();
}
public static implicit operator float(FloatPrefs value)
{
return value.Value;
}
}
public struct StringPrefs
{
private Prefs<string> m_value;
public string Value
{
get => m_value.Value;
set => m_value.Value = value;
}
public StringPrefs(string key, IGroupKey groupKey = null, string defValue = null)
{
m_value = new Prefs<string>(key, groupKey, defValue, StrAccessor.Inst);
}
public void Delete()
{
m_value.Delete();
}
public static implicit operator string(StringPrefs value)
{
return value.Value;
}
}
public struct BoolPrefs
{
private Prefs<int> m_value;
public bool Value
{
get => m_value.Value == 1;
set => m_value.Value = value ? 1 : 0;
}
public BoolPrefs(string key, IGroupKey groupKey = null, bool defValue = false)
{
m_value = new Prefs<int>(key, groupKey, defValue ? 1 : 0, IntAccessor.Inst);
}
public void Delete()
{
m_value.Delete();
}
public static implicit operator bool(BoolPrefs value)
{
return value.Value;
}
}
public struct ArrPrefs<T> where T : IComparable
{
private Prefs<string> m_value;
public ArrPrefs(string key, IGroupKey groupKey = null)
{
m_value = new Prefs<string>(key, groupKey, "", StrAccessor.Inst);
}
public T[] Get()
{
string value = m_value.Value;
if (string.IsNullOrEmpty(value))
{
return Array.Empty<T>();
}
return StrConv.ToArr<T>(value, StrConv.ArrSplitLv1);
}
public void Set(T[] value)
{
if (value == null || value.Length < 1)
{
m_value.Delete();
return;
}
var sb = SbPool.Get();
sb.Append(value[0].ToString());
for (int i = 1; i < value.Length; i++)
{
sb.Append(StrConv.ChrArrSplitLv1).Append(value[i].ToString());
}
m_value.Value = SbPool.PutAndToStr(sb);
}
public void Delete()
{
m_value.Delete();
}
}
public struct EnumPrefs<T> where T : Enum
{
private Prefs<int> m_value;
public T Value
{
get => (T)Enum.ToObject(typeof(T), m_value.Value);
set => m_value.Value = Convert.ToInt32(value);
}
public EnumPrefs(string key, IGroupKey groupKey = null, T defValue = default)
{
m_value = new Prefs<int>(key, groupKey, Convert.ToInt32(defValue), IntAccessor.Inst);
}
public void Delete()
{
m_value.Delete();
}
public static implicit operator T(EnumPrefs<T> value)
{
return value.Value;
}
}
public class IntAccessor : Prefs<int>.IPrefsAccessor
{
public static readonly IntAccessor Inst = new IntAccessor();
public bool HasKey(string key)
{
return PlayerPrefs.HasKey(key);
}
public int Get(string key)
{
return PlayerPrefs.GetInt(key);
}
public void Set(string key, int value)
{
PlayerPrefs.SetInt(key, value);
}
}
public class FloatAccessor : Prefs<float>.IPrefsAccessor
{
public static readonly FloatAccessor Inst = new FloatAccessor();
public bool HasKey(string key)
{
return PlayerPrefs.HasKey(key);
}
public float Get(string key)
{
return PlayerPrefs.GetFloat(key);
}
public void Set(string key, float value)
{
PlayerPrefs.SetFloat(key, value);
}
}
public class StrAccessor : Prefs<string>.IPrefsAccessor
{
public static readonly StrAccessor Inst = new StrAccessor();
public bool HasKey(string key)
{
return PlayerPrefs.HasKey(key);
}
public string Get(string key)
{
return PlayerPrefs.GetString(key);
}
public void Set(string key, string value)
{
PlayerPrefs.SetString(key, value);
}
}
/// <summary>
/// 分组KEY
/// </summary>
public interface IGroupKey
{
int Version { get; }
string Key { get; }
}
[Flags]
public enum RwFlag
{
None = 0,
Write = 1,
Read = 1 << 1,
Full = Write | Read
}
public static class RwFlagExt
{
public static RwFlag Mark(this RwFlag owner, RwFlag flags)
{
return owner | flags;
}
public static RwFlag Unmark(this RwFlag owner, RwFlag flags)
{
return owner & (~flags);
}
public static void MarkSelf(this ref RwFlag owner, RwFlag flags)
{
owner |= flags;
}
public static void UnmarkSelf(this ref RwFlag owner, RwFlag flags)
{
owner &= (~flags);
}
public static bool Has(this RwFlag owner, RwFlag flags)
{
return (owner & flags) == flags;
}
public static bool Overlaps(this RwFlag owner, RwFlag flags)
{
return (owner & flags) != 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7e8111bd3139471cac355bbfbbd177cc
timeCreated: 1681720464

View File

@@ -0,0 +1,226 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace YIUIFramework
{
/// <summary>
/// The priority queue is a max-heap used to find the maximum value.
/// </summary>
public sealed class PriorityQueue<T> : IEnumerable<T>
{
private IComparer<T> comparer;
private T[] heap;
private HashSet<T> fastFinder = new HashSet<T>();
/// <summary>
/// Initializes a new instance of the <see cref="PriorityQueue{T}"/>
/// class.
/// </summary>
public PriorityQueue()
: this(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PriorityQueue{T}"/>
/// class, with specify capacity.
/// </summary>
public PriorityQueue(int capacity)
: this(capacity, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PriorityQueue{T}"/>
/// class, with specify comparer.
/// </summary>
public PriorityQueue(IComparer<T> comparer)
: this(16, comparer)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PriorityQueue{T}"/>
/// class, with specify capacity and comparer.
/// </summary>
public PriorityQueue(int capacity, IComparer<T> comparer)
{
this.comparer = (comparer == null) ? Comparer<T>.Default : comparer;
this.heap = new T[capacity];
}
/// <summary>
/// Gets the count in this queue.
/// </summary>
public int Count { get; private set; }
/// <summary>
/// Gets the object at specify index.
/// </summary>
public T this[int index]
{
get { return this.heap[index]; }
}
public bool Contains(T v)
{
return fastFinder.Contains(v);
}
/// <summary>
/// Get the enumerator for this item.
/// </summary>
public IEnumerator<T> GetEnumerator()
{
return new Enumerator(this.heap, this.Count);
}
/// <summary>
/// Get the enumerator for this item.
/// </summary>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
/// <summary>
/// Clear this container.
/// </summary>
public void Clear()
{
this.Count = 0;
this.fastFinder.Clear();
}
/// <summary>
/// Push a new value into this queue.
/// </summary>
public void Push(T v)
{
if (this.Count >= this.heap.Length)
{
Array.Resize(ref this.heap, this.Count * 2);
}
this.heap[this.Count] = v;
this.SiftUp(this.Count++);
fastFinder.Add(v);
}
/// <summary>
/// Pop the max value out of this queue.
/// </summary>
public T Pop()
{
var v = this.Top();
this.heap[0] = this.heap[--this.Count];
if (this.Count > 0)
{
this.SiftDown(0);
}
fastFinder.Remove(v);
return v;
}
/// <summary>
/// Access the max value in this queue.
/// </summary>
public T Top()
{
if (this.Count > 0)
{
return this.heap[0];
}
throw new InvalidOperationException("The PriorityQueue is empty.");
}
private void SiftUp(int n)
{
var v = this.heap[n];
for (var n2 = n / 2;
n > 0 && this.comparer.Compare(v, this.heap[n2]) > 0;
n = n2, n2 /= 2)
{
this.heap[n] = this.heap[n2];
}
this.heap[n] = v;
}
private void SiftDown(int n)
{
var v = this.heap[n];
for (var n2 = n * 2; n2 < this.Count; n = n2, n2 *= 2)
{
if (n2 + 1 < this.Count &&
this.comparer.Compare(this.heap[n2 + 1], this.heap[n2]) > 0)
{
++n2;
}
if (this.comparer.Compare(v, this.heap[n2]) >= 0)
{
break;
}
this.heap[n] = this.heap[n2];
}
this.heap[n] = v;
}
/// <summary>
/// The enumerator for this <see cref="PriorityQueue{T}"/>.
/// </summary>
public struct Enumerator : IEnumerator<T>
{
private readonly T[] heap;
private readonly int count;
private int index;
/// <summary>
/// Initializes a new instance of the <see cref="Enumerator"/>
/// struct.
/// </summary>
internal Enumerator(T[] heap, int count)
{
this.heap = heap;
this.count = count;
this.index = -1;
}
/// <inheritdoc/>
public T Current
{
get { return this.heap[this.index]; }
}
/// <inheritdoc/>
object IEnumerator.Current
{
get { return this.Current; }
}
/// <inheritdoc/>
public void Dispose()
{
}
/// <inheritdoc/>
public void Reset()
{
this.index = -1;
}
/// <inheritdoc/>
public bool MoveNext()
{
return (this.index <= this.count) &&
(++this.index < this.count);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f46dc0f13c234440b3359ddb34a9c4d2
timeCreated: 1679041382

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 用于随时间重复的 重复计时器
/// </summary>
public sealed class RepeatedTimer : IDisposable
{
private LinkedListNode<Action> updateHandle;
private float leftTime;
private float repeatTime;
private bool unscaled;
private float speed = 1.0f;
private Action task;
/// <summary>
/// 获取或设置此计时器的速度
/// </summary>
public float Speed
{
get { return this.speed; }
set { this.speed = value; }
}
/// <summary>
/// 获取下一次触发的剩余时间
/// </summary>
public float LeftTime
{
get { return this.leftTime; }
}
/// <summary>
/// 获取重复时间。
/// </summary>
public float RepeatTime
{
get { return this.repeatTime; }
}
/// <summary>
/// 以指定的间隔重复调用任务
/// </summary>
public static RepeatedTimer Repeat(
float interval, Action task)
{
var timer = new RepeatedTimer();
timer.leftTime = interval;
timer.repeatTime = interval;
timer.unscaled = false;
timer.task = task;
timer.Start();
return timer;
}
/// <summary>
/// 以指定的间隔重复调用任务
/// </summary>
public static RepeatedTimer Repeat(
float delay, float interval, Action task)
{
var timer = new RepeatedTimer();
timer.leftTime = delay;
timer.repeatTime = interval;
timer.unscaled = false;
timer.task = task;
timer.Start();
return timer;
}
public void Dispose()
{
SchedulerMgr.RemoveFrameListener(this.updateHandle);
this.updateHandle = null;
}
private void Start()
{
this.updateHandle = SchedulerMgr.AddFrameListener(this.Update);
}
private void Update()
{
if (this.unscaled)
{
this.leftTime -= Time.unscaledDeltaTime * this.speed;
}
else
{
this.leftTime -= Time.deltaTime * this.speed;
}
if (this.leftTime <= 0.0f)
{
try
{
this.task();
}
catch (Exception e)
{
Logger.LogError(e);
}
finally
{
this.leftTime = this.repeatTime;
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a2870e4afdb64a5bb8b2e232c5244a18
timeCreated: 1679041383

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 119fedc32ed447dab01fbb13abf9720a
timeCreated: 1689237479

View File

@@ -0,0 +1,215 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
namespace YIUIFramework
{
/// <summary>
/// Mono的Update调度器
/// </summary>
[DisallowMultipleComponent]
public sealed partial class SchedulerMgr : MonoSingleton<SchedulerMgr>
{
// 链表 任务
private static LinkedList<Action> frameTasks = new LinkedList<Action>();
// 正在执行的
private static List<Action> executing = new List<Action>();
// 发送的任务
private static List<Action> postTasks = new List<Action>();
// 下一帧执行的任务
private static List<Action> nextFrameTasks = new List<Action>();
// 延迟执行的任务
private static List<DelayTime> delayTasks = new List<DelayTime>();
//时间缩放的延迟执行的任务
private static List<DelayTime> delayTasksWithScale = new List<DelayTime>();
//延迟任务对象的对象池
private static ObjectPool<DelayTime> DelayTimePool = new ObjectPool<DelayTime>(null, null);
//隔执行的任务
private static List<IntervalTime> intervalTasks = new List<IntervalTime>();
//当前时间
private static float now = 0;
private SchedulerMgr()
{
ClearAll();
}
protected override void OnDispose()
{
ClearAll();
}
/// <summary>
/// 清空所有任务队列。
/// </summary>
private void ClearAll()
{
frameTasks.Clear();
executing.Clear();
postTasks.Clear();
nextFrameTasks.Clear();
intervalTasks.Clear();
foreach (var task in delayTasks)
DelayTimePool.Release(task);
delayTasks.Clear();
foreach (var task in delayTasksWithScale)
DelayTimePool.Release(task);
delayTasksWithScale.Clear();
}
/*/// <summary>
/// 检查调度器的实例是否存在,如果不存在则创建一个实例。
/// 特性标签 会在游戏启动时 自动调用
/// </summary>
[RuntimeInitializeOnLoadMethod]
private static void CreateInstance()
{
var inst = Inst;
}*/
//每帧更新时调用的方法,用于执行各个任务队列中的任务。
private void Update()
{
Profiler.BeginSample("Scheduler");
now = Time.realtimeSinceStartup;
Profiler.BeginSample("Scheduler Frame Tasks");
var itr = frameTasks.First;
while (itr != null)
{
var next = itr.Next;
var value = itr.Value;
try
{
value();
}
catch (Exception e)
{
Logger.LogError(e.ToString());
frameTasks.Remove(itr);
}
itr = next;
}
Profiler.EndSample();
lock (postTasks)
{
if (postTasks.Count > 0)
{
for (int i = 0; i < postTasks.Count; ++i)
{
executing.Add(postTasks[i]);
}
postTasks.Clear();
}
}
if (nextFrameTasks.Count > 0)
{
for (int i = 0; i < nextFrameTasks.Count; ++i)
{
executing.Add(nextFrameTasks[i]);
}
nextFrameTasks.Clear();
}
for (int i = delayTasks.Count - 1; i >= 0; --i)
{
if (TestDelayTasks(delayTasks[i]))
{
DelayTimePool.Release(delayTasks[i]);
delayTasks.RemoveAt(i);
}
}
for (int i = delayTasksWithScale.Count - 1; i >= 0; --i)
{
if (TestDelayTasksWithScale(delayTasksWithScale[i]))
{
DelayTimePool.Release(delayTasksWithScale[i]);
delayTasksWithScale.RemoveAt(i);
}
}
var dt = Time.unscaledDeltaTime;
for (var i = 0; i < intervalTasks.Count; ++i)
{
var task = intervalTasks[i];
task.LeftTime -= dt;
if (task.LeftTime <= 0)
{
task.LeftTime = task.Interval;
executing.Add(task.Task);
}
intervalTasks[i] = task;
}
Profiler.BeginSample("Scheduler Executing");
this.Executing();
Profiler.EndSample();
Profiler.EndSample();
}
//检查延迟任务是否可以执行。
private bool TestDelayTasks(DelayTime task)
{
if (now >= task.Time)
{
executing.Add(task.Task);
return true;
}
return false;
}
//检查带有时间缩放的延迟任务是否可以执行。
private bool TestDelayTasksWithScale(DelayTime task)
{
task.Time -= Time.deltaTime;
if (task.Time < 0)
{
executing.Add(task.Task);
return true;
}
return false;
}
//执行正在执行的任务。
private void Executing()
{
for (int i = 0; i < executing.Count; ++i)
{
var task = executing[i];
try
{
task();
}
catch (Exception e)
{
Logger.LogError(e.ToString());
}
}
executing.Clear();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: add764274fce4398b9075a2bf90dcf94
timeCreated: 1689237456

View File

@@ -0,0 +1,113 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YIUIFramework
{
public sealed partial class SchedulerMgr
{
/// <summary>
/// 添加帧更新事件的监听器,并返回对应的节点(移除时需要)
/// </summary>
public static LinkedListNode<Action> AddFrameListener(Action action)
{
return frameTasks.AddLast(action);
}
/// <summary>
/// 移除帧更新事件的监听器。
/// </summary>
public static void RemoveFrameListener(LinkedListNode<Action> handle)
{
frameTasks.Remove(handle);
}
/// <summary>
/// 在调度器上启动一个协程。
/// </summary>
public static Coroutine RunCoroutine(IEnumerator coroutine)
{
return Inst.StartCoroutine(coroutine);
}
/// <summary>
/// 停止一个协程的执行。
/// </summary>
/// <param name="coroutine"></param>
public static void KillCoroutine(Coroutine coroutine)
{
Inst.StopCoroutine(coroutine);
}
/// <summary>
/// 工作线程向主线程发送一个任务。
/// </summary>
public static void PostTask(Action task)
{
lock (postTasks)
{
postTasks.Add(task);
}
}
/// <summary>
/// 延迟到下一帧执行一个任务
/// </summary>
public static void Delay(Action task)
{
nextFrameTasks.Add(task);
}
/// <summary>
/// 延迟一段时间后执行一个任务。
/// </summary>
public static void Delay(Action task, float time)
{
var delayTime = DelayTimePool.Get();
delayTime.Task = task;
delayTime.Time = Time.realtimeSinceStartup + time;
delayTasks.Add(delayTime);
}
/// <summary>
/// 根据时间缩放延迟一段时间后执行一个任务。
/// </summary>
public static void DelayWithScale(Action task, float time)
{
var delayTime = DelayTimePool.Get();
delayTime.Task = task;
delayTime.Time = time;
delayTasksWithScale.Add(delayTime);
}
/// <summary>
/// 循环执行一个任务,指定间隔时间。
/// </summary>
/// <returns>循环ID 停止时需要</returns>
public static int Loop(Action task, float interval)
{
var intervalTime = new IntervalTime();
intervalTime.Interval = intervalTime.LeftTime = interval;
intervalTime.Id = task.GetHashCode();
intervalTime.Task = task;
intervalTasks.Add(intervalTime);
return intervalTime.Id;
}
/// <summary>
/// 停止指定ID的循环任务
/// </summary>
public static void StopLoop(int id)
{
for (var i = 0; i < intervalTasks.Count; ++i)
{
if (intervalTasks[i].Id == id)
{
intervalTasks.RemoveAt(i);
return;
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f3e69a6cb7404847b3799eacd7cc6332
timeCreated: 1689237925

View File

@@ -0,0 +1,23 @@
using System;
namespace YIUIFramework
{
public sealed partial class SchedulerMgr
{
//用于存储延迟任务
private class DelayTime
{
public float Time;
public Action Task;
}
//用于存储间隔任务
private struct IntervalTime
{
public int Id;
public float LeftTime;
public float Interval;
public Action Task;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9ee2fb9b1d4c4bd8a8fe42e14938a099
timeCreated: 1689238226

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// This is a serializable dictionary.
/// </summary>
[Serializable]
public sealed class SerializableDictionary<TKey, TValue> :
Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
[SerializeField]
private KeyValuePair[] data;
/// <inheritdoc/>
public void OnBeforeSerialize()
{
this.data = new KeyValuePair[this.Count];
int index = 0;
foreach (var kv in this)
{
this.data[index++] = new KeyValuePair(kv.Key, kv.Value);
}
}
/// <inheritdoc/>
public void OnAfterDeserialize()
{
this.Clear();
foreach (var kv in this.data)
{
this.Add(kv.Key, kv.Value);
}
this.data = null;
}
[Serializable]
private struct KeyValuePair
{
[SerializeField]
public TKey Key;
[SerializeField]
public TValue Value;
public KeyValuePair(TKey k, TValue v)
{
this.Key = k;
this.Value = v;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6ea0f38c3e1f4930a00ede061b5557c9
timeCreated: 1679041383

View File

@@ -0,0 +1,92 @@
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// The sphere bounds.
/// </summary>
public struct SphereBounds
{
/// <summary>
/// Initializes a new instance of the <see cref="SphereBounds"/> struct.
/// </summary>
public SphereBounds(Vector3 center, float radius)
{
this.Center = center;
this.Radius = radius;
}
/// <summary>
/// Gets or sets the center of this sphere.
/// </summary>
public Vector3 Center { get; set; }
/// <summary>
/// Gets or sets the radius of this sphere.
/// </summary>
public float Radius { get; set; }
/// <summary>
/// Check whether intersects with other sphere.
/// </summary>
public bool Intersects(SphereBounds bounds)
{
var sqrDistance = (this.Center - bounds.Center).sqrMagnitude;
var minDistance = this.Radius + bounds.Radius;
return sqrDistance <= minDistance * minDistance;
}
/// <summary>
/// Check whether intersects with other AABB.
/// </summary>
public bool Intersects(Bounds bounds)
{
// Check if the sphere is inside the AABB
if (bounds.Contains(this.Center))
{
return true;
}
// Check if the sphere and the AABB intersect.
var boundsMin = bounds.min;
var boundsMax = bounds.max;
float s = 0.0f;
float d = 0.0f;
if (this.Center.x < boundsMin.x)
{
s = this.Center.x - boundsMin.x;
d += s * s;
}
else if (this.Center.x > boundsMax.x)
{
s = this.Center.x - boundsMax.x;
d += s * s;
}
if (this.Center.y < boundsMin.y)
{
s = this.Center.y - boundsMin.y;
d += s * s;
}
else if (this.Center.y > boundsMax.y)
{
s = this.Center.y - boundsMax.y;
d += s * s;
}
if (this.Center.z < boundsMin.z)
{
s = this.Center.z - boundsMin.z;
d += s * s;
}
else if (this.Center.z > boundsMax.z)
{
s = this.Center.z - boundsMax.z;
d += s * s;
}
return d <= this.Radius * this.Radius;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ef5812f3395745728c83b98ed9c43db9
timeCreated: 1679041382

View File

@@ -0,0 +1,420 @@
using System;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 处理字符串转换的类
/// </summary>
public static class StrConv
{
#region
public const string ArrSplitLv1 = "|";
public const string ArrSplitLv2 = "*";
public const string ArrSplitLv3 = "$";
public const string ArrSplitLv4 = "#";
public const char ChrArrSplitLv1 = '|';
public const char ChrArrSplitLv2 = '*';
public const char ChrArrSplitLv3 = '$';
public const char ChrArrSplitLv4 = '#';
#endregion
/// <summary>
/// 从字符串转值到u16
/// </summary>
/// <param name="valueIn"></param>
/// <param name="valueOut"></param>
/// <param name="logger">默认值为null</param>
/// <returns></returns>
public static bool ToU16(string valueIn, out ushort valueOut)
{
if (string.IsNullOrEmpty(valueIn))
{
valueOut = 0;
return false;
}
bool success = ushort.TryParse(valueIn, out valueOut);
if (!success)
{
Debug.LogError("UInt16.TryParse error");
valueOut = 0;
return false;
}
return true;
}
/// <summary>
/// 从字符串转值到u32
/// </summary>
/// <param name="valueIn"></param>
/// <param name="valueOut"></param>
/// <param name="logger">默认值为null</param>
/// <returns></returns>
public static bool ToU32(string valueIn, out uint valueOut)
{
if (string.IsNullOrEmpty(valueIn))
{
valueOut = 0;
return false;
}
bool success = uint.TryParse(valueIn, out valueOut);
if (!success)
{
Debug.LogError("UInt32.TryParse error");
valueOut = 0;
return false;
}
return true;
}
/// <summary>
/// 从字符串转值到u32直接返回值
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static uint ToU32(string value)
{
uint.TryParse(value, out uint newValue);
return newValue;
}
/// <summary>
/// 从字符串转值到u64直接返回值
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static ulong ToU64(string value)
{
ulong.TryParse(value, out ulong newValue);
return newValue;
}
/// <summary>
/// 从字符串转值到i32
/// </summary>
/// <param name="valueIn"></param>
/// <param name="valueOut"></param>
/// <param name="logger">默认值为null</param>
/// <returns></returns>
public static bool ToI32(string valueIn, out int valueOut)
{
if (string.IsNullOrEmpty(valueIn))
{
valueOut = 0;
return false;
}
bool success = Int32.TryParse(valueIn, out valueOut);
if (!success)
{
Debug.LogError("UInt32.TryParse error");
valueOut = 0;
return false;
}
return true;
}
/// <summary>
/// 从字符串转值到i32 直接返回值
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static int ToI32(string value)
{
Int32.TryParse(value, out int newValue);
return newValue;
}
/// <summary>
/// 从字符串转值到float
/// </summary>
/// <param name="valueIn"></param>
/// <param name="valueOut"></param>
/// <param name="per">默认值为1</param>
/// <param name="logger">默认值为null</param>
/// <returns></returns>
public static bool ToFloat(string valueIn, out float valueOut, float per)
{
if (string.IsNullOrEmpty(valueIn))
{
valueOut = 0;
return false;
}
bool success = float.TryParse(valueIn, out valueOut);
if (!success)
{
Debug.LogError("float.TryParse error");
valueOut = 0;
return false;
}
valueOut = valueOut * per;
return true;
}
/// <summary>
/// 解析千分比
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static float ToPer1000(string value)
{
uint v2 = ToU32(value);
return v2 * 0.001f;
}
/// <summary>
/// 从字符串转值到Byte
/// </summary>
/// <param name="valueIn"></param>
/// <param name="valueOut"></param>
/// <param name="logger"></param>
/// <returns></returns>
public static bool ToByte(string valueIn, out byte valueOut)
{
if (string.IsNullOrEmpty(valueIn))
{
valueOut = 0;
return false;
}
bool success = byte.TryParse(valueIn, out valueOut);
if (!success)
{
Debug.LogError("Byte.TryParse error");
valueOut = 0;
return false;
}
return true;
}
/// <summary>
/// 将文本转为数值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="input"></param>
/// <param name="defValue"></param>
/// <returns></returns>
public static T ToNumber<T>(string input, T defValue = default)
{
return ToNumber(input, out T value) ? value : defValue;
}
/// <summary>
/// 通用的将文本转为数值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="input"></param>
/// <param name="output"></param>
/// <returns></returns>
public static bool ToNumber<T>(string input, out T output)
{
try
{
object t;
switch (typeof(T).GetNumericType())
{
case NumericType.Int32:
int.TryParse(input, out var valueInt32);
t = valueInt32;
break;
case NumericType.UInt32:
uint.TryParse(input, out var valueUInt32);
t = valueUInt32;
break;
case NumericType.Float:
float.TryParse(input, out var valueFloat);
t = valueFloat;
break;
case NumericType.Int16:
Int16.TryParse(input, out var valueInt16);
t = valueInt16;
break;
case NumericType.Int64:
Int64.TryParse(input, out var valueInt64);
t = valueInt64;
break;
case NumericType.UInt16:
UInt16.TryParse(input, out var valueUInt16);
t = valueUInt16;
break;
case NumericType.UInt64:
UInt64.TryParse(input, out var valueUInt64);
t = valueUInt64;
break;
case NumericType.Byte:
byte.TryParse(input, out var valueByte);
t = valueByte;
break;
case NumericType.SByte:
sbyte.TryParse(input, out var valueSByte);
t = valueSByte;
break;
case NumericType.Double:
double.TryParse(input, out var valueDouble);
t = valueDouble;
break;
case NumericType.Decimal:
decimal.TryParse(input, out var valueDecimal);
t = valueDecimal;
break;
default:
output = default;
return false;
}
output = (T)t;
return true;
}
catch (Exception)
{
output = default;
return false;
}
}
/// <summary>
/// 从字符串转值到enum
/// </summary>
/// <typeparam name="TEnum"></typeparam>
/// <param name="valueIn"></param>
/// <param name="valueOut"></param>
/// <returns></returns>
public static bool ToEnum<TEnum>(string valueIn, out TEnum valueOut)
{
valueOut = (TEnum)Enum.Parse(typeof(TEnum), valueIn);
return true;
}
/// <summary>
/// 从字符串转值到enum
/// </summary>
/// <typeparam name="TEnum"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static TEnum ToEnum<TEnum>(string value)
{
return (TEnum)Enum.Parse(typeof(TEnum), value);
}
/// <summary>
/// 通过一定规则,把字符串转为数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="valueIn"></param>
/// <param name="separator"></param>
/// <param name="valueOut"></param>
/// <param name="parse">解析器</param>
/// <returns></returns>
public static bool ToArr<T>(string valueIn, string separator, out T[] valueOut, Func<string, T> parse)
{
if (string.IsNullOrEmpty(valueIn))
{
valueOut = new T[0];
return true;
}
string[] strValueArr = valueIn.Split(new[] { separator }, StringSplitOptions.None);
Type tType = typeof(T);
if (typeof(string) == tType)
{
valueOut = strValueArr as T[];
return true;
}
if (parse == null)
{
throw new NullReferenceException("如果项非string类型则必需设置解析器");
}
valueOut = new T[strValueArr.Length];
for (int i = 0; i < strValueArr.Length; i++)
{
valueOut[i] = parse(strValueArr[i]);
}
return true;
}
/// <summary>
/// 通过一定规则,把字答串数组转为对应类型数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="values"></param>
/// <param name="parse"></param>
/// <returns></returns>
public static T[] ToArr<T>(string[] values, Func<string, T> parse)
{
T[] valueOut = new T[values.Length];
for (int i = 0; i < values.Length; i++)
{
valueOut[i] = parse(values[i]);
}
return valueOut;
}
public static T[] ToArr<T>(string value, string separator = ArrSplitLv1)
{
if (ToArr(value, separator, out T[] item, ParseAny<T>))
{
return item;
}
return new T[0];
}
/// <summary>
/// 主要用在ParseArr
/// 支持string, enum, number的解析
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T ParseAny<T>(string value)
{
Type tType = typeof(T);
if (tType.IsEnum)
{
return ToEnum<T>(value);
}
if (tType == typeof(string))
{
return (T)(object)value;
}
if (!double.TryParse(value, out double doubleValue))
{
return default;
}
if (typeof(T) == typeof(double))
{
return (T)(object)doubleValue;
}
try
{
object o = Convert.ChangeType(doubleValue, typeof(T));
return (T)o;
}
catch (Exception e)
{
Debug.LogError($"Error:{e.Message}{e.StackTrace}");
return default;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c64c7164be340d4b77a043f96a93ae9
timeCreated: 1681129301

View File

@@ -0,0 +1,193 @@
using System.IO;
namespace YIUIFramework
{
public static partial class StrUtil
{
public static string Concat(string str1, string str2)
{
var sb = SbPool.Get();
sb.Append(str1).Append(str2);
return SbPool.PutAndToStr(sb);
}
public static string Concat(string str1, string str2, string str3)
{
var sb = SbPool.Get();
sb.Append(str1).Append(str2).Append(str3);
return SbPool.PutAndToStr(sb);
}
public static string Concat(params string[] param)
{
var sb = SbPool.Get();
for (int i = 0; i < param.Length; i++)
{
sb.Append(param[i]);
}
return SbPool.PutAndToStr(sb);
}
public static string Concat(params object[] param)
{
var sb = SbPool.Get();
for (int i = 0; i < param.Length; i++)
{
sb.Append(param[i]);
}
return SbPool.PutAndToStr(sb);
}
/// <summary>
/// 按头字母大写来格式化名字
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static string FormatName(string name)
{
if (string.IsNullOrEmpty(name))
{
return "";
}
StringWriter sw = new StringWriter();
bool isFirst = true;
for (int index = 0; index < name.Length; index++)
{
char c = name[index];
if (c == '_')
{
isFirst = true;
continue;
}
if (isFirst)
{
if (c >= 'a' && c <= 'z')
{
c = char.ToUpper(c);
}
isFirst = false;
}
sw.Write(c);
}
sw.Close();
return sw.ToString();
}
/// <summary>
/// 替换路径中的扩展名
/// </summary>
/// <param name="path"></param>
/// <param name="newExtension"></param>
/// <returns></returns>
public static string ReplacePathExtension(string path, string newExtension)
{
var extIndex = path.LastIndexOf('.');
if (extIndex > -1)
{
path = path.Substring(0, extIndex);
}
if (newExtension[0] == '.')
{
return path + newExtension;
}
return path + "." + newExtension;
}
/// <summary>
/// 替换文本中的占位符
/// </summary>
/// <param name="template"></param>
/// <param name="keyName"></param>
/// <param name="values"></param>
/// <returns></returns>
public static string ReplaceKeyToValue(string template, string keyName, params string[] values)
{
var sb = SbPool.Get();
var chunks = GetStrChunk(template);
for (int i = 0; i < chunks.Length; i++)
{
var chunk = chunks[i];
if (chunk.KeyIndex == 0)
{
sb.Append(chunk.TextOrKey);
continue;
}
if (chunk.TextOrKey != keyName ||
chunk.KeyIndex > values.Length)
{
sb.Append('{')
.Append(chunk.TextOrKey)
.Append(chunk.KeyIndex)
.Append('}');
continue;
}
sb.Append(values[chunk.KeyIndex - 1]);
}
return SbPool.PutAndToStr(sb);
}
/// <summary>
/// 替换字符串
/// 这个方法用于替换翔进的ReplaceString
/// 注意,因为用到非加锁缓存,所以不得用于多线程
/// </summary>
/// <param name="text"></param>
/// <param name="param"></param>
/// <returns></returns>
public static string ReplaceText(string text, params string[] param)
{
return ReplaceKeyToValue(text, "text", param);
}
/// <summary>
/// 将字符串里的英文大写转小写
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string ToLower(string s)
{
if (string.IsNullOrEmpty(s))
{
return "";
}
var length = s.Length;
bool hasChange = false;
var sb = SbPool.Get();
for (int i = 0; i < length; i++)
{
char c = s[i];
if (c >= 'A' && c <= 'Z')
{
hasChange = true;
sb.Append(char.ToLower(c));
}
else
{
sb.Append(c);
}
}
if (hasChange)
{
return SbPool.PutAndToStr(sb);
}
//如果没有改变省一个toString
SbPool.Put(sb);
return s;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 491e4d9c77264fd0804a56ad9e81833c
timeCreated: 1681720464

View File

@@ -0,0 +1,228 @@
using System;
using System.Collections.Generic;
namespace YIUIFramework
{
[Serializable]
public struct StrChunk
{
/// <summary>
/// 字符串或者key
/// 如果是字符串keyIndex = 0;
/// 如果是keykeyIndex表示索引从1开始
/// </summary>
public string TextOrKey;
/// <summary>
/// 如果StrOrKey为Key时的索引值从1开始
/// </summary>
public byte KeyIndex;
}
public static partial class StrUtil
{
/// <summary>
/// 高性能处理字符串中{%key%num}形式的占位符
/// 其中key为连续的小写字母,nul为非0开头的连续数字
/// 返回一个StrChunk数组方便使用的地方缓存以加速替换占位符
/// </summary>
/// <param name="value"></param>
/// <param name="throwError">
/// 是否抛出错误
/// 如果为false则会进行容错性解析
/// </param>
/// <returns></returns>
public static StrChunk[] GetStrChunk(string value, bool throwError = false)
{
if (string.IsNullOrEmpty(value))
{
return Array.Empty<StrChunk>();
}
var chunks = g_cacheStrChunkList;
var sb = SbPool.Get();
var keySb = SbPool.Get();
var indexSb = SbPool.Get();
int throwErrId = -1;
char lastChar = char.MaxValue;
ReadChunkState state = ReadChunkState.ReadText;
const char beginChar = '{';
const char endChar = '}';
int chrCount = value.Length;
for (int i = 0; i < chrCount; i++)
{
char c = value[i];
switch (state)
{
case ReadChunkState.ReadText:
switch (c)
{
case beginChar:
state = ReadChunkState.ReadyReadKey;
break;
case endChar:
state = ReadChunkState.Escape;
break;
default:
sb.Append(c);
break;
}
break;
case ReadChunkState.ReadyReadKey:
if (c == beginChar)
{
//{{,转义为{
sb.Append(beginChar);
state = ReadChunkState.ReadText;
break;
}
if (c < 'a' || c > 'z')
{
throwErrId = 1;
sb.Append(beginChar).Append(c);
state = ReadChunkState.ReadText;
break;
}
keySb.Append(c);
state = ReadChunkState.ReadKey;
break;
case ReadChunkState.ReadKey:
if (c >= 'a' && c <= 'z')
{
keySb.Append(c);
break;
}
if (c >= '1' && c <= '9')
{
indexSb.Append(c);
state = ReadChunkState.ReadIndex;
break;
}
throwErrId = 2;
sb.Append(beginChar).Append(keySb.ToString()).Append(c);
keySb.Clear();
state = ReadChunkState.ReadText;
break;
case ReadChunkState.ReadIndex:
if (c >= '0' && c <= '9')
{
indexSb.Append(c);
break;
}
if (c == endChar)
{
chunks.Add(new StrChunk() { TextOrKey = sb.ToString() });
chunks.Add(new StrChunk()
{
KeyIndex = byte.Parse(indexSb.ToString()),
TextOrKey = keySb.ToString()
});
sb.Clear();
}
else
{
throwErrId = 3;
sb.Append(beginChar)
.Append(keySb.ToString())
.Append(indexSb.ToString())
.Append(c);
}
keySb.Clear();
indexSb.Clear();
state = ReadChunkState.ReadText;
break;
case ReadChunkState.Escape:
if (c == lastChar)
{
sb.Append(c);
}
else
{
throwErrId = 0;
sb.Append(lastChar).Append(c);
}
state = ReadChunkState.ReadText;
break;
}
//处理错误
if (throwError && throwErrId > -1)
{
switch (throwErrId)
{
case 0:
throw new Exception(string.Format("text={3}, index={0}, chr='{1}':此处只能出现'{2}'", i, c,
lastChar, value));
case 1:
throw new Exception(string.Format("text={2}, index={0}, chr='{1}', 此处只能出现小写英文字符", i, c,
value));
case 2:
throw new Exception(string.Format("text={2}, index={0}, chr='{1}', 此处只能出现小写英文或1-9的数字", i, c,
value));
case 3:
throw new Exception(string.Format("text={2}, index={0}, chr='{1}', 0-9的数字或'}}'", i, c,
value));
}
}
lastChar = c;
}
//结尾处理
if (state != ReadChunkState.ReadText)
{
if (throwError)
{
throw new Exception("没有正确结束, state=" + state.ToString());
}
sb.Append(keySb.ToString()).Append(indexSb.ToString());
}
if (sb.Length > 0)
{
chunks.Add(new StrChunk() { TextOrKey = sb.ToString() });
}
SbPool.Put(sb);
SbPool.Put(keySb);
SbPool.Put(indexSb);
var arr = chunks.ToArray();
chunks.Clear();
return arr;
}
private static readonly List<StrChunk> g_cacheStrChunkList = new List<StrChunk>();
private enum ReadChunkState
{
ReadText,
ReadyReadKey,
ReadKey,
ReadIndex,
//转义处理
Escape
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 27c77eda32f44213af0321d4a3433014
timeCreated: 1681720464

View File

@@ -0,0 +1,122 @@
#if !UNITY_EDITOR && UNITY_ANDROID
using System.Collections.Generic;
#endif
using System.IO;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// The tool for streaming assets in unity.
/// </summary>
public static class StreamingAssets
{
#if !UNITY_EDITOR && UNITY_ANDROID
private static AndroidJavaObject assetManager;
private static Dictionary<string, HashSet<string>> folderLookup =
new Dictionary<string, HashSet<string>>();
static StreamingAssets()
{
var unityPlayerClass = new AndroidJavaClass(
"com.unity3d.player.UnityPlayer");
if (unityPlayerClass == null)
{
Debug.LogError(
"Can not find android Java class: " +
"com.unity3d.player.UnityPlayer");
return;
}
var currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>(
"currentActivity");
if (currentActivity == null)
{
Debug.LogError("Can not get method: currentActivity");
return;
}
assetManager = currentActivity.Call<AndroidJavaObject>("getAssets");
if (assetManager == null)
{
Debug.LogError("Can not get assetManager.");
return;
}
}
#endif
/// <summary>
/// Read all text from a file by specify file name in streaming asset
/// directory.
/// </summary>
public static string ReadAllText(string filePath)
{
#if !UNITY_EDITOR && UNITY_ANDROID
var inputStream = assetManager.Call<AndroidJavaObject>(
"open", filePath);
var length = inputStream.Call<int>("available");
var jniBytes = AndroidJNI.NewByteArray(length);
var clsPtr = inputStream.GetRawClass(); // AndroidJNI.FindClass("java.io.InputStream");
var METHOD_read = AndroidJNIHelper.GetMethodID(clsPtr, "read", "([B)I");
length = AndroidJNI.CallIntMethod(
inputStream.GetRawObject(),
METHOD_read,
new[] { new jvalue() { l = jniBytes } });
var bytes = AndroidJNI.FromByteArray(jniBytes);
AndroidJNI.DeleteLocalRef(jniBytes);
inputStream.Call("close");
inputStream.Dispose();
return System.Text.Encoding.ASCII.GetString(bytes, 0, length);
#else
var path = Path.Combine(
Application.streamingAssetsPath, filePath);
if (File.Exists(path))
{
return File.ReadAllText(path);
}
Debug.LogError(string.Format("<color=red> 没有读取到 :{0}</color>", path));
return string.Empty;
#endif
}
/// <summary>
/// Check whether a file existed in the folder.
/// </summary>
public static bool Existed(string filePath)
{
#if !UNITY_EDITOR && UNITY_ANDROID
var fileDir = Path.GetDirectoryName(filePath);
var fileName = Path.GetFileName(filePath);
var fileTable = GetFilesInDir(fileDir);
return fileTable.Contains(fileName);
#else
var path = Path.Combine(
Application.streamingAssetsPath, filePath);
return File.Exists(path);
#endif
}
#if !UNITY_EDITOR && UNITY_ANDROID
private static HashSet<string> GetFilesInDir(string dir)
{
HashSet<string> fileTable;
if (!folderLookup.TryGetValue(dir, out fileTable))
{
fileTable = new HashSet<string>();
var files = assetManager.Call<string[]>("list", dir);
foreach (var file in files)
{
fileTable.Add(file);
}
folderLookup.Add(dir, fileTable);
}
return fileTable;
}
#endif
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 88bf8aa1863d4eafa96114565ff21aa4
timeCreated: 1679041383

View File

@@ -0,0 +1,254 @@
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// The texture maker used to build some simple texture used in program.
/// </summary>
public static class TextureMaker
{
/// <summary>
/// Create a gray texture with specify gray.
/// </summary>
public static Texture2D Gray(float gray)
{
return Monochromatic(new Color(gray, gray, gray, 0.5f));
}
/// <summary>
/// Create a gray texture with specify gray.
/// </summary>
public static Texture2D Gray(int size, float gray)
{
return Monochromatic(size, new Color(gray, gray, gray, 0.5f));
}
/// <summary>
/// Create a monochromatic texture with specify color.
/// </summary>
public static Texture2D Monochromatic(Color color)
{
var texture = new Texture2D(
1, 1, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Point;
texture.wrapMode = TextureWrapMode.Clamp;
texture.SetPixel(0, 0, color);
texture.Apply();
return texture;
}
/// <summary>
/// Create a dot texture with specify size and color.
/// </summary>
public static Texture2D Monochromatic(int size, Color color)
{
var texture = new Texture2D(
size, size, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
texture.SetPixel(i, j, color);
}
}
texture.Apply();
return texture;
}
/// <summary>
/// Create a dot texture with specify size and color.
/// </summary>
public static Texture2D Dot(int size, Color fg, Color bg)
{
var texture = new Texture2D(
size, size, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
var radius = size / 2;
var squareRadius = (size / 2) * (size / 2);
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
var x = i - radius;
var y = j - radius;
if ((x * x) + (y * y) < squareRadius)
{
texture.SetPixel(i, j, fg);
}
else
{
texture.SetPixel(i, j, bg);
}
}
}
texture.Apply();
return texture;
}
/// <summary>
/// Create the top left corner texture with specify size and color.
/// </summary>
public static Texture2D CornerTopLeft(int size, Color fg, Color bg)
{
var texture = new Texture2D(
size, size, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
var halfsize = size / 2;
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
if (i < halfsize && j > halfsize)
{
texture.SetPixel(i, j, fg);
}
else
{
texture.SetPixel(i, j, bg);
}
}
}
texture.Apply();
return texture;
}
/// <summary>
/// Create the top right corner texture with specify size and color.
/// </summary>
public static Texture2D CornerTopRight(int size, Color fg, Color bg)
{
var texture = new Texture2D(
size, size, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
var halfsize = size / 2;
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
if (i > halfsize && j > halfsize)
{
texture.SetPixel(i, j, fg);
}
else
{
texture.SetPixel(i, j, bg);
}
}
}
texture.Apply();
return texture;
}
/// <summary>
/// Create the bottom left corner texture with specify size and color.
/// </summary>
public static Texture2D CornerBottomLeft(int size, Color fg, Color bg)
{
var texture = new Texture2D(
size, size, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
var halfsize = size / 2;
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
if (i < halfsize && j < halfsize)
{
texture.SetPixel(i, j, fg);
}
else
{
texture.SetPixel(i, j, bg);
}
}
}
texture.Apply();
return texture;
}
/// <summary>
/// Create the bottom right corner texture with specify size and color.
/// </summary>
public static Texture2D CornerBottomRight(int size, Color fg, Color bg)
{
var texture = new Texture2D(
size, size, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
var halfsize = size / 2;
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
if (i > halfsize && j < halfsize)
{
texture.SetPixel(i, j, fg);
}
else
{
texture.SetPixel(i, j, bg);
}
}
}
texture.Apply();
return texture;
}
/// <summary>
/// Create a cross texture with specify size and color.
/// </summary>
public static Texture2D Cross(
int size, int thickness, Color fg, Color bg)
{
var texture = new Texture2D(
size, size, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
if (Mathf.Abs(i - j) <= thickness ||
Mathf.Abs(i + j - size) <= thickness)
{
texture.SetPixel(i, j, fg);
}
else
{
texture.SetPixel(i, j, bg);
}
}
}
texture.Apply();
return texture;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1c2b212b568d434f811046c31c3ee336
timeCreated: 1679041382

View File

@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace YIUIFramework
{
public static class TypeExt
{
private static readonly Dictionary<Type, NumericType> g_numTypeMap;
static TypeExt()
{
var numTypeMap = new Dictionary<Type, NumericType>(11);
numTypeMap[typeof(byte)] = NumericType.Byte;
numTypeMap[typeof(sbyte)] = NumericType.SByte;
numTypeMap[typeof(short)] = NumericType.Int16;
numTypeMap[typeof(int)] = NumericType.Int32;
numTypeMap[typeof(long)] = NumericType.Int64;
numTypeMap[typeof(ushort)] = NumericType.UInt16;
numTypeMap[typeof(uint)] = NumericType.UInt32;
numTypeMap[typeof(ulong)] = NumericType.UInt64;
numTypeMap[typeof(float)] = NumericType.Float;
numTypeMap[typeof(double)] = NumericType.Double;
numTypeMap[typeof(decimal)] = NumericType.Decimal;
g_numTypeMap = numTypeMap;
}
public static NumericType GetNumericType(this Type type)
{
if (g_numTypeMap.TryGetValue(type, out NumericType value))
{
return value;
}
return NumericType.NaN;
}
/// <summary>
/// 判断一个类型是否是数值类型
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static bool IsNumericType(this Type type)
{
return g_numTypeMap.ContainsKey(type);
//也可以这样
//return !o.IsClass && !o.IsInterface && o.GetInterfaces().Any(q => q == typeof(IFormattable));
}
public static bool IsNullableNumericType(this Type type)
{
return type.Name.StartsWith("Nullable") && type.GetGenericArguments()[0].IsNumericType();
}
/// <summary>
/// 得到字段值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="fieldName"></param>
/// <param name="value"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static bool GetFieldValue<T>(this Type type, string fieldName, out T value, object obj = null)
{
var field = type.GetField(fieldName);
if (field == null)
{
value = default;
return false;
}
value = (T)field.GetValue(obj);
return true;
}
public static bool SetFieldValue(this Type type, string name, object value,
object inst = null, BindingFlags bindingArray =
BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)
{
var field = type.GetField(name, bindingArray);
if (field == null)
{
return false;
}
field.SetValue(inst, value);
return true;
}
public static object GetPropertyValue(this Type type, string name, object inst = null,
BindingFlags bindingArray =
BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)
{
var instProp = type.GetProperty(name, bindingArray);
if (instProp == null)
{
return null;
}
return instProp.GetValue(inst);
}
public static TReturn StaticCall<TReturn>(this Type type, string methodName, object[] param = null,
TReturn defReturn = default)
{
var info = type.GetMethod(methodName, BindingFlags.Static |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.FlattenHierarchy);
if (info == null)
{
return defReturn;
}
return (TReturn)info.Invoke(null, param);
}
}
public enum NumericType
{
NaN,
Byte,
SByte,
Int16,
Int32,
Int64,
UInt16,
UInt32,
UInt64,
Float,
Double,
Decimal
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9c324c1d5412412eb10a66c67bdc83e7
timeCreated: 1681129102