Merge branch 'main' of http://server.bitfall.icu:3000/root/BITKit
This commit is contained in:
commit
6788dfaa4b
|
@ -176,12 +176,7 @@ namespace BITKit
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 依赖服务提供接口
|
/// 依赖服务提供接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static ServiceProvider ServiceProvider
|
public static ServiceProvider ServiceProvider { get; set; }
|
||||||
{
|
|
||||||
get=>_serviceProvider??=ServiceCollection.BuildServiceProvider();
|
|
||||||
set => _serviceProvider = value;
|
|
||||||
}
|
|
||||||
private static ServiceProvider _serviceProvider;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 主线程
|
/// 主线程
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -8,19 +8,15 @@ namespace BITKit;
|
||||||
|
|
||||||
public class BITAppForNet
|
public class BITAppForNet
|
||||||
{
|
{
|
||||||
[Obsolete("Use InitializeAsync instead")]
|
private static readonly Timer _timer = new();
|
||||||
public static UniTask Init(string name)=>UniTask.CompletedTask;
|
|
||||||
|
|
||||||
private static Timer _timer = new();
|
private static readonly DateTime _startTime = DateTime.UtcNow;
|
||||||
|
|
||||||
private static DateTime _startTime = DateTime.UtcNow;
|
|
||||||
|
|
||||||
public static async UniTask InitializeAsync(string name)
|
public static async UniTask InitializeAsync(string name)
|
||||||
{
|
{
|
||||||
BIT4Log.OnLog += Console.WriteLine;
|
BIT4Log.OnLog += Console.WriteLine;
|
||||||
BIT4Log.OnWarning += Console.WriteLine;
|
BIT4Log.OnWarning += Console.WriteLine;
|
||||||
BIT4Log.OnException += e => Console.WriteLine(e.ToString());
|
BIT4Log.OnException += e => Console.WriteLine(e.ToString());
|
||||||
BIT4Log.OnSetConsoleColor += color => Console.ForegroundColor = color;
|
|
||||||
BIT4Log.OnNextLine += Console.WriteLine;
|
BIT4Log.OnNextLine += Console.WriteLine;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,79 +1,99 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
#if UNITY_5_3_OR_NEWER
|
#if UNITY_5_3_OR_NEWER
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace BITKit
|
namespace BITKit
|
||||||
{
|
{
|
||||||
public static class BIT4Log
|
public static class BIT4Log
|
||||||
{
|
|
||||||
#if UNITY_EDITOR && UNITY_5_3_OR_NEWER
|
|
||||||
[RuntimeInitializeOnLoadMethod]
|
|
||||||
private static void Reload()
|
|
||||||
{
|
{
|
||||||
OnLog = null;
|
#if UNITY_EDITOR && UNITY_5_3_OR_NEWER
|
||||||
OnException = null;
|
[RuntimeInitializeOnLoadMethod]
|
||||||
OnWarning = null;
|
private static void Reload()
|
||||||
OnSetConsoleColor = null;
|
{
|
||||||
OnNextLine = null;
|
OnLog = null;
|
||||||
}
|
OnException = null;
|
||||||
#endif
|
OnWarning = null;
|
||||||
public static event Action<string> OnLog;
|
OnNextLine = null;
|
||||||
public static event Action<string,Type> OnLogCallback;
|
}
|
||||||
public static event Action<Exception> OnException;
|
|
||||||
public static event Action<Exception,Type> OnExceptionCallback;
|
|
||||||
public static event Action<string> OnWarning;
|
|
||||||
public static event Action<string,Type> OnWarningCallback;
|
|
||||||
public static event Action<ConsoleColor> OnSetConsoleColor;
|
|
||||||
public static event Action OnNextLine;
|
|
||||||
private static Type currentType;
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
|
||||||
//[HideInCallstack]
|
|
||||||
#endif
|
#endif
|
||||||
public static void Log(object x, ConsoleColor color = ConsoleColor.White)
|
public static event Action<string> OnLog;
|
||||||
{
|
public static event Action<Exception> OnException;
|
||||||
OnSetConsoleColor?.Invoke(color);
|
public static event Action<string> OnWarning;
|
||||||
OnLog?.Invoke(x?.ToString());
|
public static event Action OnNextLine;
|
||||||
OnLogCallback?.Invoke(x?.ToString(),currentType);
|
|
||||||
}
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
#if UNITY_5_3_OR_NEWER
|
||||||
[HideInCallstack]
|
[HideInCallstack]
|
||||||
#endif
|
#endif
|
||||||
public static void Log<T>(object x, ConsoleColor color = ConsoleColor.White)
|
public static void Log(object x)
|
||||||
{
|
{
|
||||||
if (currentType != typeof(T))
|
if (OnLog is not null)
|
||||||
{
|
{
|
||||||
OnNextLine?.Invoke();
|
OnLog.Invoke(x?.ToString());
|
||||||
}
|
return;
|
||||||
#if NET5_0_OR_GREATER
|
}
|
||||||
Log($"[{DateTime.Now}]{typeof(T).Name}:{x}");
|
|
||||||
#else
|
|
||||||
Log($"<color=#add8e6ff><b>{typeof(T).Name}</b></color>:{x}");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
currentType = typeof(T);
|
|
||||||
}
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
#if UNITY_5_3_OR_NEWER
|
||||||
[HideInCallstack]
|
UnityEngine.Debug.Log(x);
|
||||||
#endif
|
#endif
|
||||||
public static void LogException(Exception e)
|
}
|
||||||
{
|
|
||||||
OnException?.Invoke(e);
|
|
||||||
}
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
#if UNITY_5_3_OR_NEWER
|
||||||
[HideInCallstack]
|
[HideInCallstack]
|
||||||
#endif
|
#endif
|
||||||
public static void Warning(object x)
|
public static void Log<T>(object x)
|
||||||
{
|
{
|
||||||
OnWarning?.Invoke(x.ToString());
|
if (OnLog is not null)
|
||||||
}
|
{
|
||||||
|
OnLog.Invoke(x?.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
#if UNITY_5_3_OR_NEWER
|
#if UNITY_5_3_OR_NEWER
|
||||||
[HideInCallstack]
|
UnityEngine.Debug.Log($"<b>{typeof(T).Name}</b>" + x);
|
||||||
#endif
|
#endif
|
||||||
public static void Warning<T>(object x)
|
}
|
||||||
{
|
#if UNITY_5_3_OR_NEWER
|
||||||
Warning($"<color=#ffa500ff><b>{typeof(T).Name}</b></color>:{x}");
|
[HideInCallstack]
|
||||||
|
#endif
|
||||||
|
public static void LogException(Exception e)
|
||||||
|
{
|
||||||
|
if (OnException is not null)
|
||||||
|
{
|
||||||
|
OnException.Invoke(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
UnityEngine.Debug.LogException(e);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
[HideInCallstack]
|
||||||
|
#endif
|
||||||
|
public static void Warning(object x)
|
||||||
|
{
|
||||||
|
if (OnWarning is not null)
|
||||||
|
{
|
||||||
|
OnWarning.Invoke(x.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
UnityEngine.Debug.LogWarning(x);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
[HideInCallstack]
|
||||||
|
#endif
|
||||||
|
public static void Warning<T>(object x)
|
||||||
|
{
|
||||||
|
if (OnWarning is not null)
|
||||||
|
{
|
||||||
|
OnWarning.Invoke(x.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
UnityEngine.Debug.LogWarning($"<b>{typeof(T).Name}</b>" + x);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,12 @@ namespace BITKit
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.LogException(e);
|
#if UNITY_EDITOR
|
||||||
|
UnityEngine.Debug.LogException(e);
|
||||||
|
#else
|
||||||
|
BIT4Log.LogException(e);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ using BITKit.Net.Examples;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace BITKit.Net
|
namespace BITKit.Net
|
||||||
{
|
{
|
||||||
|
@ -132,7 +133,7 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
if (IsConnecting)
|
if (IsConnecting)
|
||||||
{
|
{
|
||||||
BIT4Log.Warning<KcpNetClient>("正在连接中");
|
_logger.LogWarning("正在连接中");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_userConnected = true;
|
_userConnected = true;
|
||||||
|
@ -203,7 +204,7 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.LogException(e);
|
_logger.LogCritical(e,e.Message);
|
||||||
if (BITApp.SynchronizationContext is not null)
|
if (BITApp.SynchronizationContext is not null)
|
||||||
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
||||||
OnConnectedFailed?.Invoke();
|
OnConnectedFailed?.Invoke();
|
||||||
|
@ -223,7 +224,7 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.LogException(e);
|
_logger.LogCritical(e,e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async void OnDataInternel(ArraySegment<byte> bytes, KcpChannel channel)
|
private async void OnDataInternel(ArraySegment<byte> bytes, KcpChannel channel)
|
||||||
|
@ -255,7 +256,7 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.LogException(e);
|
_logger.LogCritical(e,e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -270,7 +271,11 @@ namespace BITKit.Net
|
||||||
Ping = (int)(DateTime.Now - _lastPingTime).TotalMilliseconds;
|
Ping = (int)(DateTime.Now - _lastPingTime).TotalMilliseconds;
|
||||||
break;
|
break;
|
||||||
case NetCommandType.ReturnToClient:
|
case NetCommandType.ReturnToClient:
|
||||||
|
|
||||||
var id = reader.ReadInt32();
|
var id = reader.ReadInt32();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (reader.ReadBoolean())
|
if (reader.ReadBoolean())
|
||||||
|
@ -281,13 +286,14 @@ namespace BITKit.Net
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var message = reader.ReadString();
|
var message = reader.ReadString();
|
||||||
|
|
||||||
_p2p.TryAdd(id,new Exception(message));
|
_p2p.TryAdd(id,new Exception(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.Warning<INetClient>($"请求返回失败:{id}");
|
_logger.LogWarning($"请求返回失败:{id}");
|
||||||
BIT4Log.LogException(e);
|
_logger.LogCritical(e,e.Message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetCommandType.GetFromClient:
|
case NetCommandType.GetFromClient:
|
||||||
|
@ -327,9 +333,9 @@ namespace BITKit.Net
|
||||||
value = methodInfo.Invoke(handle, pars);
|
value = methodInfo.Invoke(handle, pars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
BIT4Log.Warning<KcpNetClient>(path);
|
_logger.LogWarning(path);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +375,7 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.LogException(e);
|
_logger.LogCritical(e,e.Message);
|
||||||
returnWriter.Write(false);
|
returnWriter.Write(false);
|
||||||
returnWriter.Write(e.Message);
|
returnWriter.Write(e.Message);
|
||||||
}
|
}
|
||||||
|
@ -379,7 +385,7 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.LogException(e);
|
_logger.LogCritical(e,e.Message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetCommandType.AllRpc:
|
case NetCommandType.AllRpc:
|
||||||
|
@ -419,13 +425,12 @@ namespace BITKit.Net
|
||||||
reportBuilder.AppendLine($"参数{parameter.GetType()}类型匹配:{parameterInfo.ParameterType}");
|
reportBuilder.AppendLine($"参数{parameter.GetType()}类型匹配:{parameterInfo.ParameterType}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_logger.LogWarning(reportBuilder.ToString());
|
||||||
BIT4Log.Warning<KcpNetClient>(reportBuilder);
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.Warning<KcpNetClient>(rpcName);
|
_logger.LogWarning(rpcName);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,6 +444,7 @@ namespace BITKit.Net
|
||||||
|
|
||||||
if (eventDelegate is null)
|
if (eventDelegate is null)
|
||||||
{
|
{
|
||||||
|
|
||||||
//BIT4Log.Warning<KcpNetClient>($"未找到对应的事件:{rpcName}");
|
//BIT4Log.Warning<KcpNetClient>($"未找到对应的事件:{rpcName}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -451,14 +457,13 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
|
_logger.LogWarning($"未找到对应的Rpc方法:{rpcName}");
|
||||||
BIT4Log.Warning<KcpNetClient>($"未找到对应的Rpc方法:{rpcName}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_logger.LogInformation($"未知消息类型:{type},字节:{(byte)type}");
|
_logger.LogWarning($"未知消息类型:{type},字节:{(byte)type}");
|
||||||
if (bytes.Array != null)
|
if (bytes.Array != null)
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
$"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
|
$"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
|
||||||
|
@ -553,7 +558,6 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
if ((_now - startTime).TotalSeconds > RpcTimeOut)
|
if ((_now - startTime).TotalSeconds > RpcTimeOut)
|
||||||
{
|
{
|
||||||
await BITApp.SwitchToMainThread();
|
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
{
|
{
|
||||||
throw new TimeoutException("请求超时或已断开连接");
|
throw new TimeoutException("请求超时或已断开连接");
|
||||||
|
@ -561,7 +565,6 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
throw new TimeoutException($"请求超时或已断开连接,请求为{path}");
|
throw new TimeoutException($"请求超时或已断开连接,请求为{path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (_p2p.TryRemove(id, out var value))
|
if (_p2p.TryRemove(id, out var value))
|
||||||
{
|
{
|
||||||
|
@ -696,7 +699,7 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
if (DateTime.Now - _lastHeartbeat > TimeSpan.FromSeconds(5))
|
if (DateTime.Now - _lastHeartbeat > TimeSpan.FromSeconds(5))
|
||||||
{
|
{
|
||||||
BIT4Log.Warning<KcpNetClient>("心跳超时,自动断开");
|
_logger.LogWarning("心跳超时,自动断开");
|
||||||
DisconnectInternal();
|
DisconnectInternal();
|
||||||
_commandQueue.Clear();
|
_commandQueue.Clear();
|
||||||
return;
|
return;
|
||||||
|
@ -728,7 +731,7 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.LogException(e);
|
_logger.LogCritical(e,e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace BITKit.Net
|
||||||
KCPNet.Config
|
KCPNet.Config
|
||||||
);
|
);
|
||||||
_timer.Elapsed += Tick;
|
_timer.Elapsed += Tick;
|
||||||
BIT4Log.Log<KCPNetServer>("已创建KCP服务器");
|
//BIT4Log.Log<KCPNetServer>("已创建KCP服务器");
|
||||||
|
|
||||||
AddCommandListener<SimplePing>(F);
|
AddCommandListener<SimplePing>(F);
|
||||||
|
|
||||||
|
|
|
@ -130,10 +130,6 @@ namespace BITKit.Mod
|
||||||
{
|
{
|
||||||
public static async UniTask<ModPackage[]> SearchPackages()
|
public static async UniTask<ModPackage[]> SearchPackages()
|
||||||
{
|
{
|
||||||
//Todo
|
|
||||||
IUXWaiting waiting = null;
|
|
||||||
var handle = waiting?.Get();
|
|
||||||
handle?.SetMessage("正在搜索Mod包");
|
|
||||||
|
|
||||||
var list=new List<ModPackage>();
|
var list=new List<ModPackage>();
|
||||||
var path = Path.Combine(Environment.CurrentDirectory, "Mods");
|
var path = Path.Combine(Environment.CurrentDirectory, "Mods");
|
||||||
|
@ -149,7 +145,6 @@ namespace BITKit.Mod
|
||||||
list.Add(package);
|
list.Add(package);
|
||||||
}
|
}
|
||||||
|
|
||||||
waiting?.Release(handle);
|
|
||||||
return list.ToArray();
|
return list.ToArray();
|
||||||
}
|
}
|
||||||
public static async UniTask Reload()
|
public static async UniTask Reload()
|
||||||
|
@ -184,16 +179,7 @@ namespace BITKit.Mod
|
||||||
|
|
||||||
public static IMod[] Mods { get; private set; }=Array.Empty<IMod>();
|
public static IMod[] Mods { get; private set; }=Array.Empty<IMod>();
|
||||||
|
|
||||||
public static bool IsLocked
|
public static readonly ValidHandle IsBusy = new();
|
||||||
{
|
|
||||||
get => _IsLocked;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_IsLocked == value) return;
|
|
||||||
_IsLocked = value;
|
|
||||||
OnLocked?.Invoke(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static event Action<ModPackage> OnPackageLoad;
|
public static event Action<ModPackage> OnPackageLoad;
|
||||||
public static event Action<ModPackage> OnPackageLoaded;
|
public static event Action<ModPackage> OnPackageLoaded;
|
||||||
|
@ -207,179 +193,72 @@ namespace BITKit.Mod
|
||||||
|
|
||||||
public static event Action OnReload;
|
public static event Action OnReload;
|
||||||
public static event Action OnReloaded;
|
public static event Action OnReloaded;
|
||||||
|
|
||||||
public static event Action<bool> OnLocked;
|
|
||||||
|
|
||||||
public static event Func<IMod,UniTask> OnModLoadAsync;
|
public static event Func<IMod,UniTask> OnModLoadAsync;
|
||||||
public static event Func<IMod,UniTask> OnModUnloadAsync;
|
public static event Func<IMod,UniTask> OnModUnloadAsync;
|
||||||
|
|
||||||
private static CancellationTokenSource _CancellationTokenSource;
|
private static CancellationTokenSource _CancellationTokenSource;
|
||||||
private static readonly ConcurrentQueue<IMod> _RegisterQueue=new();
|
|
||||||
private static readonly ConcurrentQueue<IMod> _UnRegisterQueue = new();
|
|
||||||
private static readonly List<IMod> _CacheMods = new();
|
|
||||||
private static readonly ConcurrentDictionary<string,IMod> _InstalledMods=new();
|
private static readonly ConcurrentDictionary<string,IMod> _InstalledMods=new();
|
||||||
private static Thread _Thread;
|
|
||||||
private static bool _IsRunning;
|
|
||||||
private static bool _IsLocked;
|
|
||||||
|
|
||||||
public static void Initialize()
|
public static async UniTask Initialize()
|
||||||
{
|
{
|
||||||
BIT4Log.Log<ModService>("Mod服务已启动");
|
BIT4Log.Log<ModService>("Mod服务已启动");
|
||||||
_IsRunning = true;
|
|
||||||
_CancellationTokenSource = new CancellationTokenSource();
|
_CancellationTokenSource = new CancellationTokenSource();
|
||||||
_Thread = new Thread(InternalInitialize);
|
|
||||||
_Thread.Start();
|
|
||||||
|
|
||||||
return;
|
try
|
||||||
|
|
||||||
async void InternalInitialize()
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var modPath = Path.Combine(Environment.CurrentDirectory, "Mods\\");
|
||||||
|
PathHelper.EnsureDirectoryCreated(modPath);
|
||||||
|
var directoryInfo = new DirectoryInfo(modPath);
|
||||||
try
|
foreach (var fileInfo in directoryInfo.GetFiles())
|
||||||
{
|
{
|
||||||
var modPath = Path.Combine(Environment.CurrentDirectory, "Mods\\");
|
switch (fileInfo.Extension)
|
||||||
PathHelper.EnsureDirectoryCreated(modPath);
|
|
||||||
var directoryInfo = new DirectoryInfo(modPath);
|
|
||||||
foreach (var fileInfo in directoryInfo.GetFiles())
|
|
||||||
{
|
{
|
||||||
switch (fileInfo.Extension)
|
case ".dll":
|
||||||
{
|
{
|
||||||
case ".dll":
|
var assembly = Assembly.LoadFile(fileInfo.FullName);
|
||||||
{
|
await Load(assembly);
|
||||||
var assembly = Assembly.LoadFile(fileInfo.FullName);
|
continue;
|
||||||
await Load(assembly);
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
#if UNITY_5_3_OR_NEWER
|
||||||
case ".cs":
|
case ".cs":
|
||||||
{
|
|
||||||
var code = await File.ReadAllTextAsync(fileInfo.FullName);
|
|
||||||
var assembly = BITSharp.Compile(code);
|
|
||||||
await Load(assembly, fileInfo.DirectoryName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
BIT4Log.Warning<ModService>("自动加载Mod失败");
|
|
||||||
BIT4Log.LogException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
while (_IsRunning)
|
|
||||||
{
|
|
||||||
//todo
|
|
||||||
IUXWaiting waiting = null;
|
|
||||||
|
|
||||||
_CacheMods.Clear();
|
|
||||||
|
|
||||||
while (_UnRegisterQueue.TryDequeue(out var mod))
|
|
||||||
{
|
|
||||||
var handle = waiting?.Get();
|
|
||||||
handle?.SetMessage($":正在卸载{mod.PackageName}");
|
|
||||||
|
|
||||||
mod.OnDispose();
|
|
||||||
_CacheMods.Add(mod);
|
|
||||||
OnModUnLoad?.Invoke(mod);
|
|
||||||
|
|
||||||
waiting?.Release(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var mod in _CacheMods)
|
|
||||||
{
|
|
||||||
await mod.OnDisposeAsync(_CancellationTokenSource.Token);
|
|
||||||
foreach (var x in OnModUnloadAsync.CastAsFunc())
|
|
||||||
{
|
{
|
||||||
await x.Invoke(mod);
|
var code = await File.ReadAllTextAsync(fileInfo.FullName);
|
||||||
|
var assembly = BITSharp.Compile(code);
|
||||||
|
await Load(assembly, fileInfo.DirectoryName);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var mod in _CacheMods)
|
|
||||||
{
|
|
||||||
mod.OnDisposed();
|
|
||||||
OnModUnLoaded?.Invoke(mod);
|
|
||||||
BIT4Log.Log<ModService>($"卸载Mod:{mod.GetType().FullName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
_CacheMods.Clear();
|
|
||||||
|
|
||||||
while (_RegisterQueue.TryDequeue(out var mod))
|
|
||||||
{
|
|
||||||
var handle = waiting?.Get();
|
|
||||||
|
|
||||||
handle?.SetMessage($"正在加载:{mod.PackageName}");
|
|
||||||
|
|
||||||
_CacheMods.Add(mod);
|
|
||||||
mod.OnInitialize();
|
|
||||||
OnModLoad?.Invoke(mod);
|
|
||||||
BIT4Log.Log<ModService>($"加载Mod:{mod.GetType().FullName}");
|
|
||||||
|
|
||||||
waiting?.Release(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var mod in _CacheMods)
|
|
||||||
{
|
|
||||||
var handle = waiting?.Get();
|
|
||||||
handle?.SetMessage($"正在初始化:{mod.PackageName}");
|
|
||||||
|
|
||||||
await mod.OnInitializedAsync(_CancellationTokenSource.Token);
|
|
||||||
foreach (var x in OnModLoadAsync.CastAsFunc())
|
|
||||||
{
|
|
||||||
await x.Invoke(mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
waiting?.Release(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var mod in _CacheMods)
|
|
||||||
{
|
|
||||||
var handle = waiting?.Get();
|
|
||||||
handle?.SetMessage($":正在完成初始化中{mod.PackageName}");
|
|
||||||
|
|
||||||
mod.OnInitialized();
|
|
||||||
OnModLoaded?.Invoke(mod);
|
|
||||||
|
|
||||||
waiting?.Release(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
_CacheMods.Clear();
|
|
||||||
|
|
||||||
|
|
||||||
//Thread.Sleep(1000);
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
|
||||||
await UniTask.Delay(1000);
|
|
||||||
#else
|
|
||||||
await Task.Delay(1000);
|
|
||||||
#endif
|
#endif
|
||||||
IsLocked = false;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BIT4Log.Log<ModService>("Mod服务已停止");
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
BIT4Log.Warning<ModService>("自动加载Mod失败");
|
||||||
BIT4Log.LogException(e);
|
BIT4Log.LogException(e);
|
||||||
BIT4Log.Warning<ModService>("Mod服务遇到了错误,已停止");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
BIT4Log.LogException(e);
|
||||||
|
BIT4Log.Warning<ModService>("Mod服务遇到了错误,已停止");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Dispose()
|
public static void Dispose()
|
||||||
{_IsRunning = false;
|
{
|
||||||
_CancellationTokenSource.Cancel();
|
_CancellationTokenSource.Cancel();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_Thread.Join(100);
|
|
||||||
_RegisterQueue.Clear();
|
|
||||||
_UnRegisterQueue.Clear();
|
|
||||||
Mods = Array.Empty<IMod>();
|
Mods = Array.Empty<IMod>();
|
||||||
_InstalledMods.Clear();
|
_InstalledMods.Clear();
|
||||||
}
|
}
|
||||||
|
@ -387,8 +266,9 @@ namespace BITKit.Mod
|
||||||
{
|
{
|
||||||
BIT4Log.LogException(e);
|
BIT4Log.LogException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Load(Assembly assembly,string folderPath=null)
|
public static UniTask Load(Assembly assembly,string folderPath=null)
|
||||||
{
|
{
|
||||||
BIT4Log.Log<ModService>($"加载程序集:{assembly.FullName}");
|
BIT4Log.Log<ModService>($"加载程序集:{assembly.FullName}");
|
||||||
|
@ -480,20 +360,35 @@ namespace BITKit.Mod
|
||||||
}
|
}
|
||||||
OnPackageLoaded?.Invoke(package);
|
OnPackageLoaded?.Invoke(package);
|
||||||
}
|
}
|
||||||
public static void Load(IMod mod)
|
public static async UniTask Load(IMod mod)
|
||||||
{
|
{
|
||||||
IsLocked = true;
|
mod.OnInitialize();
|
||||||
_RegisterQueue.Enqueue(mod);
|
OnModLoad?.Invoke(mod);
|
||||||
|
BIT4Log.Log<ModService>($"加载Mod:{mod.GetType().FullName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UnLoad(IMod mod)
|
public static async UniTask UnLoad(IMod mod)
|
||||||
{
|
{
|
||||||
IsLocked = true;
|
mod.OnDispose();
|
||||||
_UnRegisterQueue.Enqueue(mod);
|
OnModUnLoad?.Invoke(mod);
|
||||||
|
|
||||||
|
await mod.OnDisposeAsync(_CancellationTokenSource.Token);
|
||||||
|
foreach (var x in OnModUnloadAsync.CastAsFunc())
|
||||||
|
{
|
||||||
|
await x.Invoke(mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.OnDisposed();
|
||||||
|
OnModUnLoaded?.Invoke(mod);
|
||||||
|
BIT4Log.Log<ModService>($"卸载Mod:{mod.GetType().FullName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Install(IMod mod)
|
public static async void Install(IMod mod)
|
||||||
{
|
{
|
||||||
|
await IsBusy;
|
||||||
|
|
||||||
|
using var _ = IsBusy.GetHandle();
|
||||||
|
|
||||||
if (_InstalledMods.ContainsKey(mod.PackageName))
|
if (_InstalledMods.ContainsKey(mod.PackageName))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Mod已安装");
|
throw new ArgumentException("Mod已安装");
|
||||||
|
@ -501,9 +396,21 @@ namespace BITKit.Mod
|
||||||
_InstalledMods.TryAdd(mod.PackageName,mod);
|
_InstalledMods.TryAdd(mod.PackageName,mod);
|
||||||
Mods = _InstalledMods.Values.ToArray();
|
Mods = _InstalledMods.Values.ToArray();
|
||||||
OnModInstalled?.Invoke(mod);
|
OnModInstalled?.Invoke(mod);
|
||||||
|
|
||||||
|
await mod.OnInitializedAsync(_CancellationTokenSource.Token);
|
||||||
|
foreach (var x in OnModLoadAsync.CastAsFunc())
|
||||||
|
{
|
||||||
|
await x.Invoke(mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.OnInitialized();
|
||||||
|
OnModLoaded?.Invoke(mod);
|
||||||
}
|
}
|
||||||
public static void UnInstall(IMod mod)
|
public static void UnInstall(IMod mod)
|
||||||
{
|
{
|
||||||
|
using var _ = IsBusy.GetHandle();
|
||||||
|
|
||||||
|
|
||||||
if(_InstalledMods.ContainsKey(mod.PackageName) is false) return;
|
if(_InstalledMods.ContainsKey(mod.PackageName) is false) return;
|
||||||
_InstalledMods.TryRemove(mod.PackageName);
|
_InstalledMods.TryRemove(mod.PackageName);
|
||||||
Mods = _InstalledMods.Values.ToArray();
|
Mods = _InstalledMods.Values.ToArray();
|
||||||
|
|
|
@ -66,12 +66,6 @@ namespace BITKit
|
||||||
{
|
{
|
||||||
var outputPath = PathHelper.GetTempFilePath();
|
var outputPath = PathHelper.GetTempFilePath();
|
||||||
|
|
||||||
//DI.TryGet<IUXWaiting>(out var waiting);
|
|
||||||
//todo
|
|
||||||
IUXWaiting waiting = null;
|
|
||||||
|
|
||||||
var handle = waiting?.Get();
|
|
||||||
handle?.SetMessage("正在编译");
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Installed is false)
|
if (Installed is false)
|
||||||
|
@ -125,7 +119,7 @@ namespace BITKit
|
||||||
// CreateNoWindow = false,
|
// CreateNoWindow = false,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
var StartInfo = new ProcessStartInfo
|
var startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
//FileName = MCSPath,
|
//FileName = MCSPath,
|
||||||
FileName = "dotnet",
|
FileName = "dotnet",
|
||||||
|
@ -142,7 +136,7 @@ namespace BITKit
|
||||||
|
|
||||||
var process = new Process()
|
var process = new Process()
|
||||||
{
|
{
|
||||||
StartInfo = StartInfo,
|
StartInfo = startInfo,
|
||||||
};
|
};
|
||||||
var reportBuilder = new StringBuilder();
|
var reportBuilder = new StringBuilder();
|
||||||
process.OutputDataReceived += (sender, args) =>
|
process.OutputDataReceived += (sender, args) =>
|
||||||
|
@ -184,14 +178,10 @@ namespace BITKit
|
||||||
|
|
||||||
BIT4Log.Log<BITSharp>(reportBuilder);
|
BIT4Log.Log<BITSharp>(reportBuilder);
|
||||||
|
|
||||||
waiting?.Release(handle);
|
|
||||||
|
|
||||||
return Assembly.Load(bytes);
|
return Assembly.Load(bytes);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
waiting?.Release(handle);
|
|
||||||
|
|
||||||
throw new Exception($"编译失败:{e}");
|
throw new Exception($"编译失败:{e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,10 +103,11 @@ namespace BITKit
|
||||||
if (IsSyncContext)
|
if (IsSyncContext)
|
||||||
{
|
{
|
||||||
await BITApp.SwitchToMainThread();
|
await BITApp.SwitchToMainThread();
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
|
await BITApp.SwitchToMainThread();
|
||||||
if (UnityEditor.EditorApplication.isPaused)
|
if (UnityEditor.EditorApplication.isPaused)
|
||||||
{
|
{
|
||||||
|
_timer.Interval = 1000d / TickRate;
|
||||||
_timer.Start();
|
_timer.Start();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -164,12 +165,19 @@ namespace BITKit
|
||||||
TickCount++;
|
TickCount++;
|
||||||
|
|
||||||
if(_isDisposed)return;
|
if(_isDisposed)return;
|
||||||
|
_timer.Interval = 1000d / TickRate;
|
||||||
_timer.Start();
|
_timer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSyncContext { get; set; } = true;
|
public bool IsSyncContext { get; set; } = true;
|
||||||
public ulong TickCount { get; set; }
|
public ulong TickCount { get; set; }
|
||||||
public int TickRate { get; set; }
|
|
||||||
|
public int TickRate
|
||||||
|
{
|
||||||
|
get => _tickRate;
|
||||||
|
set => _tickRate = Math.Clamp(value, 1, int.MaxValue);
|
||||||
|
}
|
||||||
|
private int _tickRate;
|
||||||
public bool IsConcurrent { get; set; }
|
public bool IsConcurrent { get; set; }
|
||||||
public event Func<float, UniTask> OnTickAsync;
|
public event Func<float, UniTask> OnTickAsync;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace BITKit.UX
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IUXService:IDisposable
|
public interface IUXService:IDisposable
|
||||||
{
|
{
|
||||||
|
public string SettingsPath { get; set; }
|
||||||
object Root { get; }
|
object Root { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化
|
/// 初始化
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ namespace BITKit
|
||||||
public readonly List<object> disableObjs = new List<object>();
|
public readonly List<object> disableObjs = new List<object>();
|
||||||
private bool tempEnable;
|
private bool tempEnable;
|
||||||
private Action<bool> EventOnEnableChanged;
|
private Action<bool> EventOnEnableChanged;
|
||||||
private readonly Queue<UniTaskCompletionSource> _completionSources = new();
|
private readonly ConcurrentQueue<UniTaskCompletionSource> _completionSources = new();
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
||||||
public void AddElement(object obj)
|
public void AddElement(object obj)
|
||||||
|
|
|
@ -228,9 +228,24 @@ namespace BITKit.Console
|
||||||
_commandSelector.SetMethods(null);
|
_commandSelector.SetMethods(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async void OnKeyDown(KeyDownEvent keyDownEvent)
|
private bool _stopNextFrame;
|
||||||
|
private void OnKeyDown(KeyDownEvent keyDownEvent)
|
||||||
{
|
{
|
||||||
var nextStop=true;
|
if (_stopNextFrame)
|
||||||
|
{
|
||||||
|
keyDownEvent.StopPropagation();
|
||||||
|
keyDownEvent.PreventDefault();
|
||||||
|
_stopNextFrame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (keyDownEvent.keyCode is KeyCode.BackQuote)
|
||||||
|
{
|
||||||
|
keyDownEvent.StopPropagation();
|
||||||
|
keyDownEvent.PreventDefault();
|
||||||
|
_stopNextFrame = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (keyDownEvent.keyCode)
|
switch (keyDownEvent.keyCode)
|
||||||
{
|
{
|
||||||
case KeyCode.Return:
|
case KeyCode.Return:
|
||||||
|
@ -240,35 +255,30 @@ namespace BITKit.Console
|
||||||
|
|
||||||
_textField.SetValueWithoutNotify(string.Empty);
|
_textField.SetValueWithoutNotify(string.Empty);
|
||||||
|
|
||||||
await UniTask.NextFrame();
|
|
||||||
|
|
||||||
_textField.Blur();
|
|
||||||
|
|
||||||
_textField.Focus();
|
|
||||||
|
|
||||||
BITCommands.Excute(cmd);
|
BITCommands.Excute(cmd);
|
||||||
|
|
||||||
_commandSelector.SetMethods(null);
|
_commandSelector.SetMethods(null);
|
||||||
|
|
||||||
|
keyDownEvent.StopPropagation();
|
||||||
|
keyDownEvent.PreventDefault();
|
||||||
|
_stopNextFrame = true;
|
||||||
break;
|
break;
|
||||||
case KeyCode.Tab:
|
case KeyCode.Tab:
|
||||||
|
keyDownEvent.StopPropagation();
|
||||||
|
keyDownEvent.PreventDefault();
|
||||||
break;
|
break;
|
||||||
case KeyCode.DownArrow when string.IsNullOrEmpty(_textField.text) is false:
|
case KeyCode.DownArrow when string.IsNullOrEmpty(_textField.text) is false:
|
||||||
_commandSelector.Index-=1;
|
_commandSelector.Index-=1;
|
||||||
|
keyDownEvent.StopPropagation();
|
||||||
|
keyDownEvent.PreventDefault();
|
||||||
break;
|
break;
|
||||||
case KeyCode.UpArrow when string.IsNullOrEmpty(_textField.text) is false:
|
case KeyCode.UpArrow when string.IsNullOrEmpty(_textField.text) is false:
|
||||||
_commandSelector.Index+=1;
|
_commandSelector.Index+=1;
|
||||||
break;
|
keyDownEvent.StopPropagation();
|
||||||
default:
|
keyDownEvent.PreventDefault();
|
||||||
nextStop = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextStop)
|
|
||||||
{
|
|
||||||
keyDownEvent.StopPropagation();
|
|
||||||
keyDownEvent.PreventDefault();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
private async void LogCallback(string condition, string stackTrace, LogType type)
|
private async void LogCallback(string condition, string stackTrace, LogType type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace BITKit
|
||||||
}
|
}
|
||||||
public sealed class UnityLogger<T>:ILogger<T>
|
public sealed class UnityLogger<T>:ILogger<T>
|
||||||
{
|
{
|
||||||
|
[HideInCallstack]
|
||||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||||
{
|
{
|
||||||
switch (logLevel)
|
switch (logLevel)
|
||||||
|
@ -56,7 +57,7 @@ namespace BITKit
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.Log($"<color=cyan>{typeof(T).Name}</color>:{state.ToString()}");
|
Debug.Log($"<b>{typeof(T).Name}</b>:{state.ToString()}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace BITKit
|
||||||
|
|
||||||
private void LateUpdate()
|
private void LateUpdate()
|
||||||
{
|
{
|
||||||
LateUpdateTick?.Invoke(Time.deltaTime);
|
LateUpdateTick?.Invoke(Time.deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
using UnityEngine.InputSystem;
|
using UnityEngine.InputSystem;
|
||||||
using BITKit.Mod;
|
using BITKit.Mod;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace BITKit.UX.Internal
|
namespace BITKit.UX.Internal
|
||||||
|
@ -111,7 +112,7 @@ namespace BITKit.UX
|
||||||
private readonly IUXService _uxService;
|
private readonly IUXService _uxService;
|
||||||
private VisualElement _root;
|
private VisualElement _root;
|
||||||
private VisualElement _container;
|
private VisualElement _container;
|
||||||
private bool _isInitialized = false;
|
private readonly UniTaskCompletionSource _waitUntilInitialized = new();
|
||||||
public UXContextMenu(IUXService uxService)
|
public UXContextMenu(IUXService uxService)
|
||||||
{
|
{
|
||||||
_uxService = uxService;
|
_uxService = uxService;
|
||||||
|
@ -144,11 +145,14 @@ namespace BITKit.UX
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
});
|
});
|
||||||
_isInitialized = true;
|
|
||||||
|
_waitUntilInitialized.TrySetResult();
|
||||||
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
public void Create(ContextMenuBuilder builder)
|
public async void Create(ContextMenuBuilder builder)
|
||||||
{
|
{
|
||||||
|
await _waitUntilInitialized.Task;
|
||||||
var pos = Mouse.current.position.ReadValue();
|
var pos = Mouse.current.position.ReadValue();
|
||||||
pos.y = Screen.height - pos.y;
|
pos.y = Screen.height - pos.y;
|
||||||
pos = RuntimePanelUtils.ScreenToPanel(_root.panel, pos);
|
pos = RuntimePanelUtils.ScreenToPanel(_root.panel, pos);
|
||||||
|
@ -166,9 +170,9 @@ namespace BITKit.UX
|
||||||
}
|
}
|
||||||
builder.OnExecuted += Close;
|
builder.OnExecuted += Close;
|
||||||
}
|
}
|
||||||
private void Close()
|
private async void Close()
|
||||||
{
|
{
|
||||||
if(_isInitialized is false)return;
|
await _waitUntilInitialized.Task;
|
||||||
_container.Clear();
|
_container.Clear();
|
||||||
_root.SetActive(false);
|
_root.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,7 @@ namespace BITKit.UX
|
||||||
var tabName = split[i];
|
var tabName = split[i];
|
||||||
var index = i;
|
var index = i;
|
||||||
var button = _buttons[i] = this.Create<Button>();
|
var button = _buttons[i] = this.Create<Button>();
|
||||||
|
button.AddToClassList("v"+i);
|
||||||
button.text = tabName;
|
button.text = tabName;
|
||||||
button.focusable = allowFocus;
|
button.focusable = allowFocus;
|
||||||
button.clicked += () => CurrentTab = index;
|
button.clicked += () => CurrentTab = index;
|
||||||
|
|
|
@ -25,50 +25,48 @@ namespace BITKit.UX
|
||||||
public new class UxmlFactory : UxmlFactory<TabContainer, UxmlTraits> { }
|
public new class UxmlFactory : UxmlFactory<TabContainer, UxmlTraits> { }
|
||||||
public TabContainer()
|
public TabContainer()
|
||||||
{
|
{
|
||||||
RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);
|
RegisterCallback<AttachToPanelEvent>(RebuildOnEvent);
|
||||||
RegisterCallback<DetachFromPanelEvent>(OnDetachFromPanel);
|
RegisterCallback<DetachFromPanelEvent>(RebuildOnEvent);
|
||||||
RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
RegisterCallback<GeometryChangedEvent>(RebuildOnEvent);
|
||||||
|
RegisterCallback<BlurEvent>(RebuildOnEvent);
|
||||||
|
RegisterCallback<FocusEvent>(RebuildOnEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGeometryChanged(GeometryChangedEvent evt)
|
|
||||||
{
|
|
||||||
Rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string TabPath
|
public string TabPath
|
||||||
{
|
{
|
||||||
get=>_tabPath;
|
get=>_tabPath;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_tabPath = value;
|
_tabPath = value;
|
||||||
|
Rebuild();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private string _tabPath;
|
private string _tabPath;
|
||||||
private TabBar _tabBar;
|
private TabBar _tabBar;
|
||||||
private int _index;
|
private int _index;
|
||||||
private void OnDetachFromPanel(DetachFromPanelEvent evt)
|
private void RebuildOnEvent<T>(T evt)
|
||||||
{
|
{
|
||||||
Rebuild();
|
Rebuild();
|
||||||
}
|
}
|
||||||
private void OnAttachToPanel(AttachToPanelEvent evt)
|
|
||||||
{
|
|
||||||
Rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Rebuild()
|
private void Rebuild()
|
||||||
{
|
{
|
||||||
if (_tabBar is not null)
|
if (_tabBar is not null)
|
||||||
{
|
{
|
||||||
_tabBar.OnTabChanged -= OnTabChanged;
|
_tabBar.OnTabChanged -= OnTabChanged;
|
||||||
}
|
}
|
||||||
_tabBar = panel.visualTree.Q<TabBar>(TabPath);
|
var p = parent;
|
||||||
|
while (p is not null)
|
||||||
|
{
|
||||||
|
_tabBar = p.Q<TabBar>(TabPath);
|
||||||
|
if (_tabBar is not null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = p.parent;
|
||||||
|
}
|
||||||
if (_tabBar is not null)
|
if (_tabBar is not null)
|
||||||
{
|
{
|
||||||
_tabBar.OnTabChanged += OnTabChanged;
|
_tabBar.OnTabChanged += OnTabChanged;
|
||||||
}
|
_index = _tabBar.CurrentTab;
|
||||||
if (_index <=0)
|
|
||||||
{
|
|
||||||
_index = 1;
|
|
||||||
}
|
}
|
||||||
OnTabChanged(_index);
|
OnTabChanged(_index);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +74,7 @@ namespace BITKit.UX
|
||||||
private void OnTabChanged(int obj)
|
private void OnTabChanged(int obj)
|
||||||
{
|
{
|
||||||
_index = obj;
|
_index = obj;
|
||||||
if (childCount <= 0) return;
|
if (childCount < 0) return;
|
||||||
for (var i = 0; i < childCount; i++)
|
for (var i = 0; i < childCount; i++)
|
||||||
{
|
{
|
||||||
var visualElement = this[i];
|
var visualElement = this[i];
|
||||||
|
|
|
@ -21,16 +21,10 @@ namespace BITKit.UX
|
||||||
private const string TemplatePath = "ux_mod_service_template";
|
private const string TemplatePath = "ux_mod_service_template";
|
||||||
public override bool AllowCursor => true;
|
public override bool AllowCursor => true;
|
||||||
|
|
||||||
public UXModService(IUXService uxService) : base(uxService)
|
|
||||||
{
|
|
||||||
ModService.OnModInstalled+=OnModInstalled;
|
|
||||||
ModService.OnModUnInstalled+=OnModUnInstalled;
|
|
||||||
ModService.OnModLoaded+=OnModLoaded;
|
|
||||||
ModService.OnModUnLoaded+=OnModUnLoaded;
|
|
||||||
ModService.OnLocked+=OnLocked;
|
|
||||||
}
|
|
||||||
private VisualTreeAsset _modTemplate;
|
private VisualTreeAsset _modTemplate;
|
||||||
|
[UXBindPath("open_folder-button")]
|
||||||
|
private Button _openFolderButton;
|
||||||
[UXBindPath("open-mod-button")]
|
[UXBindPath("open-mod-button")]
|
||||||
private Button _openModButton;
|
private Button _openModButton;
|
||||||
[UXBindPath("mods-container")]
|
[UXBindPath("mods-container")]
|
||||||
|
@ -43,22 +37,27 @@ namespace BITKit.UX
|
||||||
private Label _modDescriptionLabel;
|
private Label _modDescriptionLabel;
|
||||||
[UXBindPath("reload-mod-button",true)]
|
[UXBindPath("reload-mod-button",true)]
|
||||||
private Button _reloadModButton;
|
private Button _reloadModButton;
|
||||||
|
[UXBindPath("install-roslyn-fill")]
|
||||||
|
private VisualElement _installRoslynFill;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string,VisualElement> _modContainers=new();
|
private readonly ConcurrentDictionary<string,VisualElement> _modContainers=new();
|
||||||
|
public UXModService(IUXService uxService) : base(uxService)
|
||||||
|
{
|
||||||
|
ModService.OnModInstalled+=OnModInstalled;
|
||||||
|
ModService.OnModUnInstalled+=OnModUnInstalled;
|
||||||
|
ModService.OnModLoaded+=OnModLoaded;
|
||||||
|
ModService.OnModUnLoaded+=OnModUnLoaded;
|
||||||
|
ModService.IsBusy.AddListener(OnLocked);
|
||||||
|
|
||||||
private void OnLocked(bool obj)
|
OnInitiatedAsync += InitializeAsync;
|
||||||
{
|
|
||||||
RootVisualElement?.SetEnabled(!obj);
|
|
||||||
}
|
}
|
||||||
public override async UniTask EntryAsync()
|
|
||||||
|
private async UniTask InitializeAsync()
|
||||||
{
|
{
|
||||||
await base.EntryAsync();
|
_installRoslynFill.style.width = 0;
|
||||||
|
|
||||||
_modTemplate =await ModService.LoadAsset<VisualTreeAsset>(TemplatePath);
|
_modTemplate =await ModService.LoadAsset<VisualTreeAsset>(TemplatePath);
|
||||||
UXUtils.Inject(this);
|
UXUtils.Inject(this);
|
||||||
if (_openModButton is not null)
|
|
||||||
{
|
|
||||||
_openModButton.clicked += OpenMod;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_returnButton is not null)
|
if (_returnButton is not null)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +78,22 @@ namespace BITKit.UX
|
||||||
await UniTask.SwitchToMainThread();
|
await UniTask.SwitchToMainThread();
|
||||||
_reloadModButton.SetEnabled(true);
|
_reloadModButton.SetEnabled(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_openFolderButton.clicked += () =>
|
||||||
|
{
|
||||||
|
new BITApp.OpenPath()
|
||||||
|
{
|
||||||
|
path = Path.Combine(Environment.CurrentDirectory, "Mods")
|
||||||
|
}.Execute();
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnLocked(bool obj)
|
||||||
|
{
|
||||||
|
RootVisualElement?.SetEnabled(!obj);
|
||||||
|
}
|
||||||
|
|
||||||
private async void OnModUnInstalled(IMod obj)
|
private async void OnModUnInstalled(IMod obj)
|
||||||
{
|
{
|
||||||
await UniTask.SwitchToMainThread();
|
await UniTask.SwitchToMainThread();
|
||||||
|
@ -117,78 +131,6 @@ namespace BITKit.UX
|
||||||
var container = _modContainers.GetOrAdd(obj.Name,_=> Create(obj));
|
var container = _modContainers.GetOrAdd(obj.Name,_=> Create(obj));
|
||||||
container.Get<Toggle>().SetValueWithoutNotify(true);
|
container.Get<Toggle>().SetValueWithoutNotify(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OpenMod()
|
|
||||||
{
|
|
||||||
BIT4Log.Log("正在打开选择文件对话框");
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
new Thread(OpenModInternal).Start();
|
|
||||||
#else
|
|
||||||
OpenModInternal();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
|
||||||
void OpenModInternal()
|
|
||||||
{
|
|
||||||
#if UNITY_5_3_OR_NEWER && UNITY_WINDOW
|
|
||||||
BIT4Log.Log<UXModService>("已进入文件对话框线程");
|
|
||||||
new FileBrowser().OpenFileBrowser(new BrowserProperties()
|
|
||||||
{
|
|
||||||
//filterIndex = 0,
|
|
||||||
//filter = "C Sharp files (*.cs)|*.cs |Dll files (*.dll)|*.dll",
|
|
||||||
}, Filepath);
|
|
||||||
#else
|
|
||||||
throw new NotSupportedException($"{Application.platform} 不支持打开文件对话框");
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
async void Filepath(string path)
|
|
||||||
{
|
|
||||||
BIT4Log.Log<UXModService>("已选择文件:"+path);
|
|
||||||
await BITApp.SwitchToMainThread();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var file = new FileInfo(path);
|
|
||||||
|
|
||||||
switch (file.Extension)
|
|
||||||
{
|
|
||||||
case ".cs":
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
|
||||||
var code = await File.ReadAllTextAsync(path);
|
|
||||||
var assembly = BITSharp.Compile(code);
|
|
||||||
await ModService.Load(assembly,Path.GetDirectoryName(path));
|
|
||||||
#else
|
|
||||||
throw new NotSupportedException($"{Application.platform} 不支持编译C#代码");
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case ".dll":
|
|
||||||
var bytes = await File.ReadAllBytesAsync(path);
|
|
||||||
await ModService.Load(Assembly.Load(bytes),Path.GetDirectoryName(path));
|
|
||||||
break;
|
|
||||||
case ".json" when file.Name is ModPackage.DefaultFileName:
|
|
||||||
await ModService.LoadFromPackage(path);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Alert.Print(new AlertMessage()
|
|
||||||
{
|
|
||||||
title = "加载失败",
|
|
||||||
message = "不支持的文件类型"
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Alert.Print(new AlertMessage()
|
|
||||||
{
|
|
||||||
title = "加载失败",
|
|
||||||
message = e.Message
|
|
||||||
});
|
|
||||||
BIT4Log.LogException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
private VisualElement Create(IMod mod)
|
private VisualElement Create(IMod mod)
|
||||||
{
|
{
|
||||||
var container =_modsContainer.Create(_modTemplate);
|
var container =_modsContainer.Create(_modTemplate);
|
||||||
|
@ -219,7 +161,7 @@ namespace BITKit.UX
|
||||||
ModService.OnModUnInstalled-=OnModUnInstalled;
|
ModService.OnModUnInstalled-=OnModUnInstalled;
|
||||||
ModService.OnModLoaded-=OnModLoaded;
|
ModService.OnModLoaded-=OnModLoaded;
|
||||||
ModService.OnModUnLoaded-=OnModUnLoaded;
|
ModService.OnModUnLoaded-=OnModUnLoaded;
|
||||||
ModService.OnLocked-=OnLocked;
|
ModService.IsBusy.RemoveListener(OnLocked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ using Debug = UnityEngine.Debug;
|
||||||
|
|
||||||
namespace BITKit.UX
|
namespace BITKit.UX
|
||||||
{
|
{
|
||||||
public abstract class UIToolKitPanel : IUXPanel
|
public abstract class UIToolKitPanel : IUXPanel,IDisposable
|
||||||
{
|
{
|
||||||
public const string USSEntry = "transition_entry";
|
public const string USSEntry = "transition_entry";
|
||||||
public const string USSEntryAsync = "transition_entry_async";
|
public const string USSEntryAsync = "transition_entry_async";
|
||||||
|
@ -128,6 +128,7 @@ namespace BITKit.UX
|
||||||
public virtual bool AllowCursor { get; }
|
public virtual bool AllowCursor { get; }
|
||||||
public virtual bool AllowInput { get; }
|
public virtual bool AllowInput { get; }
|
||||||
public virtual string[] InitialUssClasses { get; } = Array.Empty<string>();
|
public virtual string[] InitialUssClasses { get; } = Array.Empty<string>();
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
public bool IsEntered { get; set; }
|
public bool IsEntered { get; set; }
|
||||||
protected virtual void OnReturn()
|
protected virtual void OnReturn()
|
||||||
|
@ -247,6 +248,12 @@ namespace BITKit.UX
|
||||||
public virtual void OnTick(float deltaTime)
|
public virtual void OnTick(float deltaTime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
RootVisualElement?.RemoveFromHierarchy();
|
||||||
|
IsDisposed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace BITKit.UX
|
||||||
protected readonly IUXService UXService;
|
protected readonly IUXService UXService;
|
||||||
protected VisualElement RootVisualElement { get; set; }
|
protected VisualElement RootVisualElement { get; set; }
|
||||||
protected bool IsInitialized { get; private set; }
|
protected bool IsInitialized { get; private set; }
|
||||||
|
protected readonly UniTaskCompletionSource WaitUntilInitialized = new();
|
||||||
protected UIToolkitOverlay(IUXService uxService, CancellationTokenSource cancellationToken)
|
protected UIToolkitOverlay(IUXService uxService, CancellationTokenSource cancellationToken)
|
||||||
{
|
{
|
||||||
UXService = uxService;
|
UXService = uxService;
|
||||||
|
@ -40,6 +41,8 @@ namespace BITKit.UX
|
||||||
|
|
||||||
UXUtils.Inject(this);
|
UXUtils.Inject(this);
|
||||||
IsInitialized = true;
|
IsInitialized = true;
|
||||||
|
|
||||||
|
WaitUntilInitialized.TrySetResult();
|
||||||
}
|
}
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,6 +71,7 @@ namespace BITKit.UX
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void ClearHistory() => History.Clear();
|
public static void ClearHistory() => History.Clear();
|
||||||
|
|
||||||
|
public string SettingsPath { get; set; } = "ux_panel_settings";
|
||||||
public object Root { get; private set; }
|
public object Root { get; private set; }
|
||||||
public async UniTask InitializeAsync()
|
public async UniTask InitializeAsync()
|
||||||
{
|
{
|
||||||
|
@ -86,7 +87,7 @@ Object.Destroy(gameObject);
|
||||||
var document = gameObject.AddComponent<UIDocument>();
|
var document = gameObject.AddComponent<UIDocument>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var panelSettings =await ModService.LoadAsset<PanelSettings>("ux_panel_settings");
|
var panelSettings =await ModService.LoadAsset<PanelSettings>(SettingsPath);
|
||||||
document.panelSettings = panelSettings;
|
document.panelSettings = panelSettings;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
@ -102,7 +102,16 @@ namespace BITKit
|
||||||
handle.VisualElement.RemoveFromHierarchy();
|
handle.VisualElement.RemoveFromHierarchy();
|
||||||
_visibleHandle.RemoveElement(handle);
|
_visibleHandle.RemoveElement(handle);
|
||||||
}
|
}
|
||||||
_visibleHandle.Invoke();
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_visibleHandle.Invoke();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async UniTask InitializeAsync()
|
public override async UniTask InitializeAsync()
|
||||||
|
@ -116,6 +125,8 @@ namespace BITKit
|
||||||
|
|
||||||
UXUtils.Inject(this);
|
UXUtils.Inject(this);
|
||||||
_container.Clear();
|
_container.Clear();
|
||||||
|
|
||||||
|
_visibleHandle.Invoke();
|
||||||
|
|
||||||
_initializationState = InitializationState.Initialized;
|
_initializationState = InitializationState.Initialized;
|
||||||
}
|
}
|
||||||
|
|
|
@ -714,5 +714,48 @@ namespace BITKit
|
||||||
|
|
||||||
self.SetOpacity(visible ? 1 : 0);
|
self.SetOpacity(visible ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ClearTooltipsOnPointerLeave(this VisualElement visualElement)
|
||||||
|
{
|
||||||
|
visualElement.RegisterCallback<PointerLeaveEvent>(OnLeave);
|
||||||
|
return;
|
||||||
|
|
||||||
|
void OnLeave(PointerLeaveEvent evt)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(visualElement.tooltip) is false)
|
||||||
|
visualElement.tooltip = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void BlinkingCursor(this TextField tf,int interval=1000)
|
||||||
|
{
|
||||||
|
tf.schedule.Execute(() =>
|
||||||
|
{
|
||||||
|
if(tf.ClassListContains("transparentCursor"))
|
||||||
|
tf.RemoveFromClassList("transparentCursor");
|
||||||
|
else
|
||||||
|
tf.AddToClassList("transparentCursor");
|
||||||
|
}).Every(interval);
|
||||||
|
}
|
||||||
|
public static Vector2 GetAbsolutePositionInUI(this VisualElement element)
|
||||||
|
{
|
||||||
|
var position = Vector2.zero;
|
||||||
|
var currentElement = element;
|
||||||
|
|
||||||
|
// 遍历每一个父元素,并累计位置
|
||||||
|
while (currentElement != null)
|
||||||
|
{
|
||||||
|
var style = currentElement.resolvedStyle;
|
||||||
|
|
||||||
|
// 累加该元素相对于父元素的位置
|
||||||
|
position.x += style.left;
|
||||||
|
position.y += style.top;
|
||||||
|
|
||||||
|
// 移动到父元素
|
||||||
|
currentElement = currentElement.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ MonoBehaviour:
|
||||||
m_FallbackDpi: 96
|
m_FallbackDpi: 96
|
||||||
m_ReferenceResolution: {x: 1920, y: 1080}
|
m_ReferenceResolution: {x: 1920, y: 1080}
|
||||||
m_ScreenMatchMode: 0
|
m_ScreenMatchMode: 0
|
||||||
m_Match: 0.421
|
m_Match: 0.5
|
||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
m_TargetDisplay: 0
|
m_TargetDisplay: 0
|
||||||
m_ClearDepthStencil: 1
|
m_ClearDepthStencil: 1
|
||||||
|
|
|
@ -93,6 +93,37 @@ TabBar Button:disabled {
|
||||||
margin-left: 32px;
|
margin-left: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gap-8 {
|
||||||
|
margin-top: -8px;
|
||||||
|
margin-right: -8px;
|
||||||
|
margin-bottom: -8px;
|
||||||
|
margin-left: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-8 > * {
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-x-8 {
|
||||||
|
margin-right: -8px;
|
||||||
|
margin-left: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-x-8 > * {
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-y-8 {
|
||||||
|
margin-top: -8px;
|
||||||
|
margin-bottom: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-y-8 > * {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.r-8 {
|
.r-8 {
|
||||||
border-top-left-radius: 8px;
|
border-top-left-radius: 8px;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
|
@ -473,3 +504,7 @@ Button.clear {
|
||||||
border-top-color: rgba(0, 0, 0, 0);
|
border-top-color: rgba(0, 0, 0, 0);
|
||||||
border-bottom-color: rgba(0, 0, 0, 0);
|
border-bottom-color: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabContainer > * {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||||
<ui:Template name="ModTemplate" src="project://database/Assets/BITKit/Unity/UX/ModTemplate.uxml?fileID=9197481963319205126&guid=5d8350eb5da74b34a81d90d7fdea10c7&type=3#ModTemplate" />
|
<ui:Template name="ModTemplate" src="project://database/Assets/BITKit/Unity/UX/ux_mod_service_template.uxml?fileID=9197481963319205126&guid=5d8350eb5da74b34a81d90d7fdea10c7&type=3#ux_mod_service_template" />
|
||||||
<Style src="project://database/Assets/BITKit/Unity/UX/Common/Common.uss?fileID=7433441132597879392&guid=a3a69d3518fd02b489e721f3c5b0b539&type=3#Common" />
|
<Style src="project://database/Assets/BITKit/Unity/UX/Common/Common.uss?fileID=7433441132597879392&guid=a3a69d3518fd02b489e721f3c5b0b539&type=3#Common" />
|
||||||
<Style src="project://database/Assets/BITKit/Unity/UX/UXModService.uss?fileID=7433441132597879392&guid=4603eeaf39bae3448a93680711a15c42&type=3#UXModService" />
|
<Style src="project://database/Assets/BITKit/Unity/UX/UXModService.uss?fileID=7433441132597879392&guid=4603eeaf39bae3448a93680711a15c42&type=3#UXModService" />
|
||||||
<Style src="project://database/Assets/BITKit/Unity/UX/BITAlert.uss?fileID=7433441132597879392&guid=8d0db0fee932f5342988f09217d6309a&type=3#BITAlert" />
|
<Style src="project://database/Assets/BITKit/Unity/UX/BITAlert.uss?fileID=7433441132597879392&guid=8d0db0fee932f5342988f09217d6309a&type=3#BITAlert" />
|
||||||
|
@ -31,12 +31,13 @@
|
||||||
<ui:VisualElement style="width: 384px; margin-left: 64px;">
|
<ui:VisualElement style="width: 384px; margin-left: 64px;">
|
||||||
<ui:Label tabindex="-1" text="Mod列表" parse-escape-sequences="true" display-tooltip-when-elided="true" class="tl" />
|
<ui:Label tabindex="-1" text="Mod列表" parse-escape-sequences="true" display-tooltip-when-elided="true" class="tl" />
|
||||||
<ui:VisualElement name="info-container" style="flex-grow: 1;">
|
<ui:VisualElement name="info-container" style="flex-grow: 1;">
|
||||||
<ui:VisualElement name="mod-image" style="height: 256px; background-color: rgba(0, 0, 0, 0); background-image: url('project://database/Assets/BITKit/Unity/Art/Images/Mod_Package.png?fileID=2800000&guid=7ef0888883a3a7442989365c2dc57862&type=3#Mod_Package'); -unity-background-scale-mode: scale-and-crop;" />
|
<ui:VisualElement name="mod-image" style="height: 256px; background-color: rgba(0, 0, 0, 0); background-image: url("project://database/Assets/BITKit/Unity/Art/Images/Mod_Package.png?fileID=2800000&guid=7ef0888883a3a7442989365c2dc57862&type=3#Mod_Package"); -unity-background-scale-mode: scale-and-crop;" />
|
||||||
<ui:VisualElement style="padding-top: 8px; padding-right: 0; padding-bottom: 8px; padding-left: 0; flex-grow: 1;">
|
<ui:VisualElement style="padding-top: 8px; padding-right: 0; padding-bottom: 8px; padding-left: 0; flex-grow: 1;">
|
||||||
<ui:Label tabindex="-1" text="加载一个Mod" parse-escape-sequences="true" display-tooltip-when-elided="true" name="mod-name-label" class="tl" />
|
<ui:Label tabindex="-1" text="加载一个Mod" parse-escape-sequences="true" display-tooltip-when-elided="true" name="mod-name-label" class="tl" />
|
||||||
<ui:Label tabindex="-1" text="通过Windows Explorer选择Mod后,需要等待一段时间才能加载,这是因为explorer内部的延迟 可以直接加载编译好的dll 加载.cs需要安装MonoBleedingEdge 已加载的脚本mod无法动态完成卸载,可能需要重启应用 动态加载的Mod不会保存,如需要每次启动都自动加载,需要将Mod放置在/Mods/{ModName}/文件夹中,并创建PackageInfo.json描述文件" parse-escape-sequences="true" display-tooltip-when-elided="true" name="mod-description-label" style="white-space: normal;" />
|
<ui:Label tabindex="-1" text="通过Windows Explorer选择Mod后,需要等待一段时间才能加载,这是因为explorer内部的延迟 可以直接加载编译好的dll 加载.cs需要安装MonoBleedingEdge 已加载的脚本mod无法动态完成卸载,可能需要重启应用 动态加载的Mod不会保存,如需要每次启动都自动加载,需要将Mod放置在/Mods/{ModName}/文件夹中,并创建PackageInfo.json描述文件" parse-escape-sequences="true" display-tooltip-when-elided="true" name="mod-description-label" style="white-space: normal;" />
|
||||||
<ui:VisualElement style="flex-grow: 1;" />
|
<ui:VisualElement style="flex-grow: 1;" />
|
||||||
<ui:Button text="打开开发手册" parse-escape-sequences="true" display-tooltip-when-elided="true" name="open-manual-button" />
|
<ui:Button text="打开开发手册" parse-escape-sequences="true" display-tooltip-when-elided="true" name="open-manual-button" />
|
||||||
|
<ui:Button text="打开Mod目录" parse-escape-sequences="true" display-tooltip-when-elided="true" name="open_folder-button" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.UIElements;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TextCore.Text;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace BITKit.GameEditor
|
||||||
|
{
|
||||||
|
public class TMPFontCheck : EditorWindow
|
||||||
|
{
|
||||||
|
public static FontAsset CurrentFont;
|
||||||
|
[MenuItem("Tools/TextMeshPro Font Check")]
|
||||||
|
public static void ShowExample()
|
||||||
|
{
|
||||||
|
GetWindow<TMPFontCheck>().Show();
|
||||||
|
}
|
||||||
|
private void CreateGUI()
|
||||||
|
{
|
||||||
|
rootVisualElement.Clear();
|
||||||
|
|
||||||
|
var refreshButton = rootVisualElement.Create<Button>();
|
||||||
|
refreshButton.text = "刷新";
|
||||||
|
refreshButton.clicked += CreateGUI;
|
||||||
|
|
||||||
|
var mergeButton = rootVisualElement.Create<Button>();
|
||||||
|
mergeButton.text = "合并字符串";
|
||||||
|
|
||||||
|
var fontField = rootVisualElement.Create<ObjectField>();
|
||||||
|
fontField.objectType = typeof(FontAsset);
|
||||||
|
|
||||||
|
fontField.RegisterValueChangedCallback(x =>
|
||||||
|
{
|
||||||
|
CurrentFont = x.newValue as FontAsset;
|
||||||
|
});
|
||||||
|
fontField.SetValueWithoutNotify(CurrentFont);
|
||||||
|
|
||||||
|
var container = rootVisualElement.Create<VisualElement>();
|
||||||
|
container.style.flexDirection = FlexDirection.Column;
|
||||||
|
|
||||||
|
var label = container.Create<Label>();
|
||||||
|
label.style.unityFontDefinition = new FontDefinition()
|
||||||
|
{
|
||||||
|
fontAsset = CurrentFont
|
||||||
|
};
|
||||||
|
|
||||||
|
var textfield = container.Create<TextField>();
|
||||||
|
textfield.label = "Test Font";
|
||||||
|
textfield.multiline = true;
|
||||||
|
|
||||||
|
textfield.RegisterValueChangedCallback(x =>
|
||||||
|
{
|
||||||
|
label.text = x.newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
textfield.style.unityFontDefinition = label.style.unityFontDefinition;
|
||||||
|
|
||||||
|
mergeButton.clicked += () =>
|
||||||
|
{
|
||||||
|
textfield.value =new string(Regex.Replace(textfield.value, @"\s+", "").Distinct().ToArray());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 707aad4d7f4d82c46866eb25231c2388
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue