This commit is contained in:
CortexCore
2024-11-03 16:38:17 +08:00
parent 056e2cada5
commit 4ba741408d
4693 changed files with 2445 additions and 5443 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using AYellowpaper.SerializedCollections;
using UnityEngine;
@@ -9,11 +10,19 @@ namespace BITKit
public class SetTargetFrameRate : MonoBehaviour
{
[SerializeField] private SerializedDictionary<string, int> frameRateDictionary;
[SerializeField] private int startFrameRate;
[SerializeField] private SerializedDictionary<RuntimePlatform, bool> maxFrameRate;
private int currentFrameRate;
private void Start()
{
currentFrameRate = Application.targetFrameRate;
if(maxFrameRate.TryGetValue(Application.platform,out var max))
{
if (max)
{
var maxRate = Screen.resolutions.Max(x => x.refreshRateRatio.value);
Application.targetFrameRate = currentFrameRate = (int)maxRate;
}
}
}
public void SetFrameRate(string key)
{

View File

@@ -155,100 +155,105 @@ namespace BITKit
try
{
_progressLabel.text="正在更新资源包版本...";
var operation = package.UpdatePackageVersionAsync();
try
if (isOffline is false)
{
onGetCurrentVersion.Invoke(package.GetPackageVersion());
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
while (operation.IsDone is false)
{
await UniTask.NextFrame(destroyCancellationToken);
//_progressBar.value = operation.Progress;
_setProgressValue?.Invoke(operation.Progress);
}
_progressLabel.text = "正在更新资源包版本...";
var operation = package.UpdatePackageVersionAsync();
try
{
onGetCurrentVersion.Invoke(package.GetPackageVersion());
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
while (operation.IsDone is false)
{
await UniTask.NextFrame(destroyCancellationToken);
//_progressBar.value = operation.Progress;
_setProgressValue?.Invoke(operation.Progress);
}
if (operation.Status == EOperationStatus.Succeed)
{
//更新成功
string packageVersion = operation.PackageVersion;
Debug.Log($"Updated package Version : {packageVersion}");
_progressLabel.text="正在更新资源包清单...";
var manifestOperation = package.UpdatePackageManifestAsync(packageVersion);
await manifestOperation.ToUniTask();
if (manifestOperation.Status == EOperationStatus.Succeed)
if (operation.Status == EOperationStatus.Succeed)
{
//更新成功
int downloadingMaxNum = 10;
int failedTryAgain = 3;
var downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);
//没有需要下载的资源
if (downloader.TotalDownloadCount != 0)
{
//需要下载的文件总数和总大小
int totalDownloadCount = downloader.TotalDownloadCount;
long totalDownloadBytes = downloader.TotalDownloadBytes;
downloader.OnDownloadProgressCallback = (totalDownloadCount, currentDownloadCount, totalDownloadBytes, currentDownloadBytes) =>
{
BIT4Log.Log<BITFramework>($"{totalDownloadCount},{currentDownloadCount},{totalDownloadBytes},{currentDownloadBytes}");
//下载进度
float progress = (float)currentDownloadBytes / totalDownloadBytes;
_setProgressValue?.Invoke(progress);
_setProgressLabel?.Invoke($"{currentDownloadBytes}/{totalDownloadBytes}");
};
downloader.OnDownloadErrorCallback=(fileName,error) =>
{
_setProgressLabel?.Invoke(error);
};
//注册回调方法
// downloader.OnDownloadErrorCallback = OnDownloadErrorFunction;
// downloader.OnDownloadProgressCallback = OnDownloadProgressUpdateFunction;
// downloader.OnDownloadOverCallback = OnDownloadOverFunction;
// downloader.OnStartDownloadFileCallback = OnStartDownloadFileFunction;
string packageVersion = operation.PackageVersion;
Debug.Log($"Updated package Version : {packageVersion}");
//开启下载
downloader.BeginDownload();
await downloader;
//检测下载结果
if (downloader.Status != EOperationStatus.Succeed)
_progressLabel.text = "正在更新资源包清单...";
var manifestOperation = package.UpdatePackageManifestAsync(packageVersion);
await manifestOperation.ToUniTask();
if (manifestOperation.Status == EOperationStatus.Succeed)
{
//更新成功
int downloadingMaxNum = 10;
int failedTryAgain = 3;
var downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);
//没有需要下载的资源
if (downloader.TotalDownloadCount != 0)
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text =operation.Error;
//需要下载的文件总数和总大小
int totalDownloadCount = downloader.TotalDownloadCount;
long totalDownloadBytes = downloader.TotalDownloadBytes;
downloader.OnDownloadProgressCallback = (totalDownloadCount, currentDownloadCount,
totalDownloadBytes, currentDownloadBytes) =>
{
BIT4Log.Log<BITFramework>(
$"{totalDownloadCount},{currentDownloadCount},{totalDownloadBytes},{currentDownloadBytes}");
//下载进度
float progress = (float)currentDownloadBytes / totalDownloadBytes;
_setProgressValue?.Invoke(progress);
_setProgressLabel?.Invoke($"{currentDownloadBytes}/{totalDownloadBytes}");
};
downloader.OnDownloadErrorCallback = (fileName, error) =>
{
_setProgressLabel?.Invoke(error);
};
//注册回调方法
// downloader.OnDownloadErrorCallback = OnDownloadErrorFunction;
// downloader.OnDownloadProgressCallback = OnDownloadProgressUpdateFunction;
// downloader.OnDownloadOverCallback = OnDownloadOverFunction;
// downloader.OnStartDownloadFileCallback = OnStartDownloadFileFunction;
//开启下载
downloader.BeginDownload();
await downloader;
//检测下载结果
if (downloader.Status != EOperationStatus.Succeed)
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text = operation.Error;
}
}
}
else
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text = operation.Error;
}
}
else
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text =operation.Error;
_progressLabel.text = operation.Error;
}
}
else
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text =operation.Error;
}
}
catch (Exception e)
{
BIT4Log.LogException(e);
_progressLabel.text =e.Message;
BIT4Log.LogException(e);
_progressLabel.text = e.Message;
}
_setProgressLabel?.Invoke("资源系统初始化完成,后处理中...");
afterInitialize.Invoke(_setProgressValue,_setProgressLabel);
@@ -281,14 +286,22 @@ namespace BITKit
if (loadEntryScene.Allow)
{
_progressLabel.text="正在加载场景...";
await package.LoadSceneAsync(loadEntryScene.Value);
if (document)
Destroy(document);
try
{
await package.LoadSceneAsync(loadEntryScene.Value);
_progressLabel.text="场景加载完成...";
}
catch (Exception e)
{
Debug.LogException(e);
await UniTask.NextFrame();
_progressLabel.text = e.Message;
}
}
else
{
if (document)
Destroy(document);
_progressLabel.text="未找到默认场景,正在加载场景[1]";
SceneManager.LoadScene(1);
}
}
@@ -298,6 +311,8 @@ namespace BITKit
_progressBar.value =0;
_progressLabel.text = e.Message;
}
if (document)
Destroy(document);
}
private void OnDestroy()

View File

@@ -6,7 +6,7 @@ using YooAsset;
/// <summary>
/// 资源文件查询服务类
/// </summary>
public class GameQueryServices : IBuildinQueryServices
public class GameQueryServices
{
public bool Query(string packageName, string fileName)
{

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BITKit.Mod;
using Cysharp.Threading.Tasks;
using UnityEngine;
using YooAsset;
using Object = UnityEngine.Object;
namespace BITKit.IO
{
public class YooAssetModHelper : MonoBehaviour
{
private void OnEnable()
{
ModService.LoadAssetAsyncFactory += LoadAsset;
}
private void OnDisable()
{
ModService.LoadAssetAsyncFactory -= LoadAsset;
}
private static async UniTask<object> LoadAsset(string arg)
{
var handle = YooAssets.LoadAssetAsync(arg);
await handle;
return handle.AssetObject;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 4db757ff244ea044882f208ebcd638e9
guid: 31eceddc48b358b40901eba1134d5450
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -7,7 +7,10 @@ using UnityEngine;
using Cysharp.Threading.Tasks;
using System.Threading.Tasks;
using BITKit.UX;
using Microsoft.Extensions.DependencyInjection;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
using Debug = UnityEngine.Debug;
#if !UNITY_EDITOR
@@ -107,7 +110,7 @@ namespace BITKit
}
public static void ThrowIfWindowNotFocus()
{
#if UNITY_EDITOR
#if UNITY_EDITOR && ENABLE_INPUT_SYSTEM
switch (Camera.main)
{
case {} camera:
@@ -132,10 +135,8 @@ namespace BITKit
[RuntimeInitializeOnLoadMethod]
private static void Reload()
{
IsPlaying = true;
BIT4Log.OnLog += Debug.Log;
BIT4Log.OnWarning += Debug.LogWarning;
BIT4Log.OnException += Debug.LogException;
//启动BITApp
BITApp.SynchronizationContext = SynchronizationContext.Current;
BITApp.Start(Application.productName, new BITApp.AppSettings()).Forget();
@@ -148,34 +149,42 @@ namespace BITKit
DontDestroyOnLoad(GameObject);
AllowCursor.AddListener(ToggleCursor);
AllowTouchSupport.AddListener(ToggleTouchSupport);
}
static void ToggleCursor(bool active)
private static void ToggleCursor(bool active)
{
Cursor.lockState = active ? CursorLockMode.None : CursorLockMode.Locked;
Cursor.visible = active;
}
static void ToggleTouchSupport(bool active)
private static void ToggleTouchSupport(bool active)
{
#if ENABLE_INPUT_SYSTEM
if (active)
{
UnityEngine.InputSystem.EnhancedTouch.EnhancedTouchSupport.Enable();
}
else
{
UnityEngine.InputSystem.EnhancedTouch.EnhancedTouchSupport.Disable();
}
{
UnityEngine.InputSystem.EnhancedTouch.EnhancedTouchSupport.Enable();
}
else
{
UnityEngine.InputSystem.EnhancedTouch.EnhancedTouchSupport.Disable();
}
#endif
}
[BITCommand]
public static async void Exit()
{
await BITApp.SwitchToMainThread();
BITApp.Stop();
Data.Clear();
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
[SerializeField, ReadOnly] private bool allowCursor;
private void Start()
{
BIT4Log.Log<BITApp>($"已创建{nameof(BITApp)}");
@@ -193,6 +202,7 @@ namespace BITKit
BITApp.Time.ElapsedTime = Time.time;
BITApp.Time.DeltaTime = Time.deltaTime;
BITApp.Time.TimeAsDouble = Time.timeAsDouble;
allowCursor = AllowCursor.Allow;
}
public string GetName()

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 6c35d9b0aa735fb4da16818146dcb1b2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 0aba5e6fd19c3bd448cb7e6a2445281d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f301a4601a248544a951fda0f6b99dca
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 27edfa6d5b14e9744bee44ea568e2184
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 78c6958aff6c5b440a97c1ed312ec999
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 754fca19a35c2174397a08140fcbd2de
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 3d0224f76fd199646b1e002a99a80b3c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 5b9aca415732ded4bbcff452ea709712
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 4718485b2b78cbb4b8e3cd04c04ba6f8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 16e02814826ddb340bdf893f7670c5a3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 2bf9525189b5e794da1ee266cecc3cad
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 0f88bfa12271b0d48a7eff562428583b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -6,7 +6,6 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Events;
using Debug = UnityEngine.Debug;

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: cac7e494c3644094590640578295e381
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d8076169c923ca34ba7dcb4d2cde6f08
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 94558e646275a304085feb375803fa4d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using UnityEngine;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace BITKit
{
public sealed class UnityLogger:ILogger
{
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
switch (logLevel)
{
case LogLevel.Critical:
case LogLevel.Error:
if (exception is not null)
{
Debug.LogException(exception);
}
else
{
Debug.LogError($"{CurrentScope}:{state.ToString()}");
}
break;
default:
Debug.Log($"{CurrentScope}:{state.ToString()}");
break;
}
}
public bool IsEnabled(LogLevel logLevel) => true;
private string CurrentScope { get; set; }
public IDisposable BeginScope<TState>(TState state) where TState : notnull
{
CurrentScope = typeof(TState).Name;
return null;
}
}
public sealed class UnityLoggerProvider:ILoggerProvider
{
public void Dispose()
{
}
public ILogger CreateLogger(string categoryName)
{
return new UnityLogger();
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 64fa60f31192679458dff793286a1b4b
guid: 5a5707d216b0705449ea7839ef72c70a
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c61177c00bf2de24ebc4de76df9e7566
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e3d8df889cc95ab4c96da546aef8e6b3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f3f9d9aba85bc8e4191eb784a8401652
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: b14253370170a22438a528b58b06f2aa
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 59e92c009b8465542b35a144c16dee00
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c8df93123c1bf1b4da65995b571737c8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f93325d7f3a8dcd44a1b6118e5c40d25
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,228 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using BITKit;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace BITKit.Net
{
[Serializable]
public sealed class GameNet : INetClient,INetServer,INetProvider
{
private static INetClient _netClientImplementation=>GameNetProvider.NetClient;
private static INetProvider _netProviderImplementation=>GameNetProvider.NetProvider;
private static INetServer _netServerImplementation1=>GameNetProvider.NetServer;
object INetClient.Source => _netClientImplementation.Source;
object INetServer.Source => _netServerImplementation1.Source;
public event Action OnStartConnect
{
add => _netClientImplementation.OnStartConnect += value;
remove => _netClientImplementation.OnStartConnect -= value;
}
public event Action OnConnected
{
add => _netClientImplementation.OnConnected += value;
remove => _netClientImplementation.OnConnected -= value;
}
public event Action OnDisconnected
{
add => _netClientImplementation.OnDisconnected += value;
remove => _netClientImplementation.OnDisconnected -= value;
}
public event Action OnConnectedFailed
{
add => _netClientImplementation.OnConnectedFailed += value;
remove => _netClientImplementation.OnConnectedFailed -= value;
}
public bool IsConnected => _netClientImplementation.IsConnected;
bool INetServer.ManualTick
{
get => _netServerImplementation1.ManualTick;
set => _netServerImplementation1.ManualTick = value;
}
bool INetClient.ManualTick
{
get => _netClientImplementation.ManualTick;
set => _netClientImplementation.ManualTick = value;
}
public int Ping => _netClientImplementation.Ping;
public int Id => _netClientImplementation.Id;
public void Disconnect()
{
_netClientImplementation.Disconnect();
}
public UniTask<bool> Connect(string address = "localhost", ushort port = 27014)
{
return _netClientImplementation.Connect(address, port);
}
public void SendServerMessage(string message)
{
_netClientImplementation.SendServerMessage(message);
}
public void ServerCommand<T>(T command = default)
{
_netProviderImplementation.ServerCommand(command);
}
public void AllClientCommand<T>(T command = default)
{
_netProviderImplementation.AllClientCommand(command);
}
public void ClientCommand<T>(int id, T command)
{
_netProviderImplementation.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(string path=default,params object[] pars)=>_netProviderImplementation.GetFromServer<T>(path,pars);
public UniTask<T> GetFromClient<T>(int id,string path=default, params object[] pars)=>_netProviderImplementation.GetFromClient<T>(id,path, pars);
public void AddRpcHandle(object rpcHandle)
{
_netProviderImplementation.AddRpcHandle(rpcHandle);
}
public void AddCommandListener<T>(Action<T> handle)
{
_netProviderImplementation.AddCommandListener(handle);
}
public void RemoveCommandListener<T>(Action<T> handle)
{
_netProviderImplementation.RemoveCommandListener(handle);
}
public void AddCommandListener<T>(Func<T, UniTask<T>> func)
{
_netProviderImplementation.AddCommandListener(func);
}
public void RemoveCommandListener<T>(Func<T, UniTask<T>> func)
{
_netProviderImplementation.RemoveCommandListener(func);
}
public void SendRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendRT(rpcName, pars);
}
public void SendTargetRT(int id, string rpcName, params object[] pars)
{
_netProviderImplementation.SendTargetRT(id, rpcName, pars);
}
public void SendAllRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendAllRT(rpcName, pars);
}
public void Tick()
{
_netProviderImplementation.Tick();
}
public void HandShake()
{
_netProviderImplementation.HandShake();
}
public event Action<int> OnClientConnected
{
add => _netServerImplementation1.OnClientConnected += value;
remove => _netServerImplementation1.OnClientConnected -= value;
}
public event Action<int> OnClientDisconnected
{
add => _netServerImplementation1.OnClientDisconnected += value;
remove => _netServerImplementation1.OnClientDisconnected -= value;
}
public event Action OnStartServer
{
add => _netServerImplementation1.OnStartServer += value;
remove => _netServerImplementation1.OnStartServer -= value;
}
public event Action OnStopServer
{
add => _netServerImplementation1.OnStopServer += value;
remove => _netServerImplementation1.OnStopServer -= value;
}
public void StartServer(ushort port = 27014)
{
_netServerImplementation1.StartServer(port);
}
public void StopServer(bool dispose = false)
{
_netServerImplementation1.StopServer(dispose);
}
public bool IsRunningServer => _netServerImplementation1 is { IsRunningServer: true };
public void SendMessageToClient(int id, string message)
{
_netServerImplementation1.SendMessageToClient(id, message);
}
public void SendMessageToAll(string message)
{
_netServerImplementation1.SendMessageToAll(message);
}
public IDictionary<int, EndPoint> Connections => _netServerImplementation1.Connections;
public void AddCommandListenerWithId<T>(Action<int, T> handle)
{
_netServerImplementation1.AddCommandListenerWithId(handle);
}
public void KickClient(int id)
{
_netServerImplementation1.KickClient(id);
}
}
public class GameNetProvider : MonoBehaviour
{
public static INetClient NetClient { get; private set; }
public static INetServer NetServer { get; private set; }
public static INetProvider NetProvider => (NetClient, NetServer) switch
{
(not null,null)=>NetClient as INetProvider,
(null,not null)=>NetServer as INetProvider,
(not null, { IsRunningServer: true }) =>NetServer as INetProvider,
({ IsConnected: true },not null) =>NetClient as INetProvider,
_ => null
};
[SerializeField] private MonoBehaviour netClient;
[SerializeField] private MonoBehaviour netServer;
private void Awake()
{
NetClient = netClient as INetClient;
NetServer = netServer as INetServer;
}
}
}

View File

@@ -1,279 +0,0 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using BITKit.Net.Examples;
using UnityEngine;
using Cysharp.Threading.Tasks;
namespace BITKit.Net.Kcp
{
[CustomType(typeof(INetClient))]
[CustomType(typeof(INetProvider))]
public class MonoKcpClient : MonoBehaviour,INetClient,INetProvider
{
internal static MonoKcpClient Singleton { get; private set; }
[SerializeField,ReadOnly] private int rate;
[SerializeReference,SubclassSelector] private ITicker ticker;
[SerializeField] private string m_host;
[SerializeField] private ushort m_port;
[SerializeField] private bool connectOnStart;
[SerializeField] private bool autoReconnect;
[Header(Constant.Header.Debug)]
[SerializeField]
[ReadOnly] private int id;
[SerializeField]
[ReadOnly]private Vector2 traffic;
[SerializeField]
[ReadOnly]private string upTraffic;
[SerializeField]
[ReadOnly]private string downTraffic;
[SerializeField, ReadOnly] private bool isConnected;
#if UNITY_EDITOR
[SerializeField] private Optional<string> allowDebugHost;
[SerializeField] private Optional<ushort> allowDebugPort;
#endif
private KcpNetClient client;
private INetClient _netClientImplementation=>client;
private INetProvider _netProviderImplementation=>client;
private readonly IntervalUpdate _reconnectInterval = new(3);
public event Action OnStartConnect
{
add => _netClientImplementation.OnStartConnect += value;
remove => _netClientImplementation.OnStartConnect -= value;
}
public event Action OnConnected
{
add => _netClientImplementation.OnConnected += value;
remove => _netClientImplementation.OnConnected -= value;
}
public event Action OnDisconnected
{
add => _netClientImplementation.OnDisconnected += value;
remove => _netClientImplementation.OnDisconnected -= value;
}
public event Action OnConnectedFailed
{
add => _netClientImplementation.OnConnectedFailed += value;
remove => _netClientImplementation.OnConnectedFailed -= value;
}
public bool IsConnected => _netClientImplementation.IsConnected;
public bool ManualTick
{
get => client.ManualTick;
set => client.ManualTick = value;
}
public int Ping => _netClientImplementation.Ping;
public int Id => _netClientImplementation.Id;
public void Disconnect()
{
_netClientImplementation.Disconnect();
}
public UniTask<bool> Connect(string address = "localhost", ushort port = 27014)
{
if(address is "localhost" or null)
address = m_host;
if(port is 27014 or 0)
port = m_port;
m_host = address;
m_port = port;
return _netClientImplementation.Connect(address, port);
}
public void SendServerMessage(string message)
{
_netClientImplementation.SendServerMessage(message);
}
public void ServerCommand<T>(T command = default)
{
_netProviderImplementation.ServerCommand(command);
}
public void AllClientCommand<T>(T command = default)
{
_netProviderImplementation.AllClientCommand(command);
}
public void ClientCommand<T>(int id, T command)
{
_netProviderImplementation.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(string path = null, params object[] pars)
{
return client.GetFromServer<T>(path, pars);
}
public UniTask<T> GetFromClient<T>(int id, string path = null, params object[] pars)
{
return client.GetFromClient<T>(id, path, pars);
}
public UniTask<T> GetFromServer<T>(string path=null,T command = default)
{
return _netProviderImplementation.GetFromServer<T>(path,command);
}
public UniTask<T> GetFromClient<T>(int id,string path=null, T command = default)
{
return _netProviderImplementation.GetFromClient<T>(id,path, command);
}
public void AddRpcHandle(object rpcHandle)
{
_netProviderImplementation.AddRpcHandle(rpcHandle);
}
public void AddCommandListener<T>(Action<T> handle)
{
_netProviderImplementation.AddCommandListener(handle);
}
public void RemoveCommandListener<T>(Action<T> handle)
{
_netProviderImplementation.RemoveCommandListener(handle);
}
public void AddCommandListener<T>(Func<T, UniTask<T>> func)
{
_netProviderImplementation.AddCommandListener(func);
}
public void RemoveCommandListener<T>(Func<T, UniTask<T>> func)
{
_netProviderImplementation.RemoveCommandListener(func);
}
public void SendRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendRT(rpcName, pars);
}
public void SendTargetRT(int id, string rpcName, params object[] pars)
{
_netProviderImplementation.SendTargetRT(id, rpcName, pars);
}
public void SendAllRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendAllRT(rpcName, pars);
}
public void Tick()
{
_netProviderImplementation.Tick();
}
public void HandShake()
{
_netProviderImplementation.HandShake();
}
private void Awake()
{
Singleton = this;
client = new KcpNetClient();
}
private void Start()
{
if (ticker is not null)
{
ManualTick = true;
ticker.Add(OnTick);
}
destroyCancellationToken.Register(() =>
{
if (IsConnected)
Disconnect();
ticker?.Remove(OnTick);
});
if (!connectOnStart) return;
#if UNITY_EDITOR
var _host = allowDebugHost.Allow ? allowDebugHost.Value : m_host;
var _port = allowDebugPort.Allow ? allowDebugPort.Value : m_port;
Connect(_host, _port).Forget();
#else
Connect(m_host, m_port).Forget();
#endif
}
private void OnTick(float obj)
{
if (destroyCancellationToken.IsCancellationRequested) return;
client.AutoReconnect = autoReconnect;
id = Id;
Tick();
traffic = client.Traffic;
upTraffic = NetUtils.GetFileSize((long)traffic.x);
downTraffic = NetUtils.GetFileSize((long)traffic.y);
isConnected = IsConnected;
}
[BIT]
private void EditorConnect()
{
BITAppForUnity.ThrowIfNotPlaying();
Connect(m_host, m_port).Forget();
}
[BIT]
private void EditorDisconnect()
{
BITAppForUnity.ThrowIfNotPlaying();
Disconnect();
}
[BIT]
private async void Hello()
{
BITAppForUnity.ThrowIfNotPlaying();
var stopWatch = new Stopwatch();
stopWatch.Start();
var value =await GetFromServer<SimplePing>(null,new SimplePing()
{
StartTime = DateTime.Now
});
stopWatch.Stop();
BIT4Log.Log<MonoKcpClient>($"已返回\n开始:{value.StartTime}\n结束:{value.EndTime}\n延迟:{stopWatch.ElapsedMilliseconds}ms");
SendRT(nameof(KCPNetServer.OnNetRpcTest),64,12.8f,true);
stopWatch.Reset();
stopWatch.Start();
var hello =
await GetFromServer<string>(
nameof(KCPNetServer.MyRpcTest),
"hello"
);
stopWatch.Stop();
BIT4Log.Log<MonoKcpClient>($"已返回\n{hello}\n延迟:{stopWatch.ElapsedMilliseconds}ms");
stopWatch.Reset();
stopWatch.Start();
var helloAsync =
await GetFromServer<string>(
nameof(KCPNetServer.MyRpcTestAsync),
"hello"
);
stopWatch.Stop();
BIT4Log.Log<MonoKcpClient>($"已返回\n{helloAsync},\n延迟:{stopWatch.ElapsedMilliseconds}ms");
}
}
}

View File

@@ -1,196 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace BITKit.Net.Kcp
{
public class MonoKcpServer : MonoBehaviour,INetServer,INetProvider
{
[SerializeField, ReadOnly] private int rate;
[SerializeField] private ushort initialPort;
[SerializeReference,SubclassSelector] private ITicker ticker;
private INetServer _netServerImplementation => _server;
private KCPNetServer _server=>_serverInstance??=new KCPNetServer();
private KCPNetServer _serverInstance;
public bool ManualTick
{
get => _netServerImplementation.ManualTick;
set => _netServerImplementation.ManualTick = value;
}
public event Action<int> OnClientConnected
{
add => _netServerImplementation.OnClientConnected += value;
remove => _netServerImplementation.OnClientConnected -= value;
}
public event Action<int> OnClientDisconnected
{
add => _netServerImplementation.OnClientDisconnected += value;
remove => _netServerImplementation.OnClientDisconnected -= value;
}
public event Action OnStartServer
{
add => _netServerImplementation.OnStartServer += value;
remove => _netServerImplementation.OnStartServer -= value;
}
public event Action OnStopServer
{
add => _netServerImplementation.OnStopServer += value;
remove => _netServerImplementation.OnStopServer -= value;
}
public void StartServer(ushort port = 27014)
{
if(port == 27014)port = initialPort;
_netServerImplementation.StartServer(port);
}
public void StopServer(bool dispose = false)
{
_netServerImplementation.StopServer(dispose);
}
public bool IsRunningServer => _netServerImplementation.IsRunningServer;
public void SendMessageToClient(int id, string message)
{
_netServerImplementation.SendMessageToClient(id, message);
}
public void SendMessageToAll(string message)
{
_netServerImplementation.SendMessageToAll(message);
}
public IDictionary<int, EndPoint> Connections => _netServerImplementation.Connections;
public void AddCommandListenerWithId<T>(Action<int, T> handle)
{
_netServerImplementation.AddCommandListenerWithId(handle);
}
public void KickClient(int id)
{
_netServerImplementation.KickClient(id);
}
[BIT]
private void EditorStartServer()
{
BITAppForUnity.ThrowIfNotPlaying();
StartServer(initialPort);
}
[BIT]
private void EditorStopServer()
{
BITAppForUnity.ThrowIfNotPlaying();
StopServer();
}
[BIT]
private void RandomAPort()
{
initialPort = (ushort)UnityEngine.Random.Range(10000, ushort.MaxValue);
}
public void ServerCommand<T>(T command = default)
{
_server.ServerCommand(command);
}
public void AllClientCommand<T>(T command = default)
{
_server.AllClientCommand(command);
}
public void ClientCommand<T>(int id, T command)
{
_server.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(string path = null, params object[] pars)
{
return _serverInstance.GetFromServer<T>(path, pars);
}
public UniTask<T> GetFromClient<T>(int id, string path = null, params object[] pars)
{
return _serverInstance.GetFromClient<T>(id, path, pars);
}
public void AddRpcHandle(object rpcHandle)
{
_server.AddRpcHandle(rpcHandle);
}
public void AddCommandListener<T>(Action<T> handle)
{
_server.AddCommandListener(handle);
}
public void AddCommandListener<T>(Func<T,UniTask<T>> func)
{
_serverInstance.AddCommandListener(func);
}
public void RemoveCommandListener<T>(Func<T,UniTask<T>> func)
{
_serverInstance.RemoveCommandListener(func);
}
public void RemoveCommandListener<T>(Action<T> handle)
{
_server.RemoveCommandListener(handle);
}
public void SendRT(string rpcName, params object[] pars)
{
_server.SendRT(rpcName, pars);
}
public void SendTargetRT(int id, string rpcName, params object[] pars)
{
_server.SendTargetRT(id, rpcName, pars);
}
public void SendAllRT(string rpcName, params object[] pars)
{
_server.SendAllRT(rpcName, pars);
}
public void Tick()
{
_server.Tick();
}
public void HandShake()
{
_server.HandShake();
}
private void Start()
{
if (ticker is not null)
{
ManualTick = true;
ticker.Add(OnTick);
}
destroyCancellationToken.Register(() =>
{
if (IsRunningServer)
StopServer(true);
ticker?.Remove(OnTick);
});
}
private void OnTick(float deltaTime)
{
Tick();
}
}
}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: ff89031c06983164e96d3e7f39202bd6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 0575f8a71b53c294280850c69ebc948b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,18 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 934c1d4517c77c84c9ac8a52d8f409d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a8b1b06afa8596f40a587e91fcafee3b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 828cff26ade6425449bdfa7f6215e35f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: ca4d6f6a0b605f04380126f5978cfd06
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 37ee4cd3b00fbec49b4b2fdfa8ade433
guid: a5212c0ab664e774ea4416f9c389858a
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,12 +1,8 @@
{
"name": "BITKit.MotionMatching",
"name": "BITKit.Physics",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:d525ad6bd40672747bde77962f1c401e",
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:296866320aab85a42a0403bf684bac59"
"GUID:14fe60d984bf9f84eac55c6ea033a8f4"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 3e9ced9430d8ee743b37f99f97066130
guid: 89bd0da52dc3cc94daadea6252c6ad1b
AssemblyDefinitionImporter:
externalObjects: {}
userData:

View File

@@ -0,0 +1,140 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace BITKit.Physics
{
public class GetClosePointFromCollider : IClosePointProvider
{
public string Name="Default";
public Transform Transform;
public Vector3 Offset = default;
public LayerMask LayerMask=LayerMask.NameToLayer("Default");
public float Distance=1.6f;
public float MinHeight=0.32f;
public float MaxHeight = 1f;
private readonly Collider[] _colliders=new Collider[8];
private readonly Collider[] _mainCollider=new Collider[8];
public GetClosePointFromCollider(Transform transform)
{
Transform = transform;
}
public bool TryGetValue(out Vector3 position, out Collider collider)
{
Vector3 vector3 = default;
StringBuilder reportBuilder = new();
reportBuilder.AppendLine($"检测任务:{Name}");
position = Transform.position + Transform.rotation * Offset;
var detectedLength = UnityEngine.Physics.OverlapSphereNonAlloc(position, Distance, _mainCollider, LayerMask);
reportBuilder.AppendLine($"检测到了{detectedLength}个碰撞体");
foreach (var collider1 in _mainCollider.Take(detectedLength).OrderBy(ByTop).Reverse())
//for (var i = 0; i <detectedLength ; i++)
{
//reportBuilder.AppendLine($"----------------------------检测到了碰撞体{_mainCollider[i].name}");
//var collider = _mainCollider[i];
if (collider1.isTrigger)
{
reportBuilder?.AppendLine("碰撞体是触发器");
continue;
}
switch (collider1)
{
case MeshCollider meshCollider:
if (meshCollider.convex is false)
{
reportBuilder?.AppendLine("MeshCollider未勾选Convex");
continue;
}
break;
}
var bounds = collider1.bounds;
vector3 = collider1.ClosestPoint(Transform.position + Vector3.up * 64);
var top = bounds.center.y + bounds.extents.y;
Debug.DrawLine(Transform.position, Transform.position + Vector3.up * top, Color.blue, 8f);
if (Transform.position.y + MinHeight > top)
{
reportBuilder?.AppendLine("高度不足");
continue;
}
var nextPos = position;
nextPos.y = collider1.bounds.center.y;
{
var ray = new Ray(nextPos, Transform.forward);
if (collider1.Raycast(new Ray(nextPos, Transform.forward), out _, Distance) is false)
{
reportBuilder?.AppendLine("未检测到前方");
Debug.DrawRay(ray.origin,ray.direction,Color.red,Distance);
continue;
}
}
var height = Mathf.Abs(top - Transform.position.y);
if (height > MaxHeight)
{
reportBuilder?.AppendLine($"高度差距过大:{height}");
continue;
}
if (UnityEngine.Physics.Linecast(Transform.position, vector3, out var raycastHit2, LayerMask))
{
if (raycastHit2.collider != collider1)
{
reportBuilder?.AppendLine($"检测到了其他碰撞体:{raycastHit2.transform.name}");
continue;
}
}
var length = UnityEngine.Physics.OverlapSphereNonAlloc(vector3, 0.01f, _colliders, LayerMask);
switch (length)
{
case 1:
if (_colliders[0] != collider1)
{
reportBuilder.AppendLine($"检测到了其他碰撞体{_colliders[0].name}");
continue;
}
break;
case > 1:
reportBuilder.AppendLine("检测到了更多碰撞体");
for (var ii = 0; ii < length; ii++)
{
//Debug.DrawLine(vector3, _colliders[ii].ClosestPoint(vector3), Color.red, 8);
reportBuilder.AppendLine($"\t{_colliders[ii].name}");
}
continue;
}
vector3.y = top;
position = vector3;
collider = collider1;
reportBuilder.AppendLine("<color=green>成功</color>");
//BIT4Log.Log<GetClosePointFromCollider>(reportBuilder.ToString());
return true;
}
collider = null;
//BIT4Log.Log<GetClosePointFromCollider>(reportBuilder.ToString());
return false;
}
private float ByTop(Collider arg)
{
return arg.bounds.center.y + arg.bounds.extents.y;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: e97c2d299cde4c14eae93069ecb68701
guid: adae51e53fcfc08438543b2a0759aa10
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit.Physics
{
public interface IClosePointProvider
{
bool TryGetValue(out Vector3 position, out Collider collider);
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 23c7dbd4bc26161488daef24f737e581
guid: c6d564c448ca14a4cb07a132d63c9930
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 8dbc9adf34f58644791e2defdc12ad23
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: aa12ed18c1564e54a952f9b2de915181
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: fcd7f58396b844c469be67a483cca248
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d500662d808c54d45abc4ec1a483b103
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 3117808dcb65bf6478fc0302b73aa0f3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,59 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit
{
public class Selectable : MonoBehaviour, ISelectable
{
public Transform GetTransform() => transform;
private void Start()
{
OnNone?.Invoke();
}
public Transform Transform =>this? transform:null;
public void SetSelectionState(SelectionState state)
{
switch (state)
{
case SelectionState.None:
OnNone?.Invoke();
break;
case SelectionState.Hover:
OnHover?.Invoke();
break;
case SelectionState.Active:
OnActive?.Invoke();
break;
case SelectionState.Inactive:
OnInactive?.Invoke();
break;
case SelectionState.Focus:
OnFocus?.Invoke();
break;
case SelectionState.Selected:
OnSelected?.Invoke();
break;
case SelectionState.Enabled:
OnEnabled?.Invoke();
break;
case SelectionState.Checked:
OnChecked?.Invoke();
break;
case SelectionState.Root:
OnRoot?.Invoke();
break;
}
}
public event Action OnNone;
public event Action OnHover;
public event Action OnActive;
public event Action OnInactive;
public event Action OnFocus;
public event Action OnSelected;
public event Action OnEnabled;
public event Action OnChecked;
public event Action OnRoot;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: cc54ec95ef8983c43ba8ef43dae16792
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,46 +0,0 @@
using System;
using UnityEngine;
using UnityEngine.Events;
namespace BITKit
{
public class SelectableEvent : MonoBehaviour
{
[Header(nameof(SelectionState.None))]
[SerializeField] private UnityEvent OnNone;
[Header(nameof(SelectionState.Hover))]
[SerializeField]private UnityEvent OnHover;
[Header(nameof(SelectionState.Active))]
[SerializeField]private UnityEvent OnActive;
[Header(nameof(SelectionState.Inactive))]
[SerializeField]private UnityEvent OnInactive;
[Header(nameof(SelectionState.Focus))]
[SerializeField]private UnityEvent OnFocus;
[Header(nameof(SelectionState.Selected))]
[SerializeField]private UnityEvent OnSelected;
[Header(nameof(SelectionState.Enabled))]
[SerializeField]private UnityEvent OnEnabled;
[Header(nameof(SelectionState.Checked))]
[SerializeField]private UnityEvent OnChecked;
[Header(nameof(SelectionState.Root))]
[SerializeField]private UnityEvent OnRoot;
private void Start()
{
var selectable = GetComponent<ISelectable>();
if (selectable == null)
{
Debug.LogError($"No {nameof(ISelectable)} component found on {gameObject.name}");
return;
}
selectable.OnNone += OnNone.Invoke;
selectable.OnHover += OnHover.Invoke;
selectable.OnActive += OnActive.Invoke;
selectable.OnInactive += OnInactive.Invoke;
selectable.OnFocus += OnFocus.Invoke;
selectable.OnSelected += OnSelected.Invoke;
selectable.OnEnabled += OnEnabled.Invoke;
selectable.OnChecked += OnChecked.Invoke;
selectable.OnRoot += OnRoot.Invoke;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 6ad098f307334e54dbcffd896748414c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c19adb38837ea354cac76ac0f21d35f5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1c3ae7dc4edbe894f8ecd28cb0057e54
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -22,6 +22,10 @@ namespace BITKit
public void Add(Action<float> action)=>GameTickService.Add(action);
public void Remove(Action<float> action)=>GameTickService.Remove(action);
public void ManualTick(float delta)
{
throw new NotImplementedException();
}
}
[CustomType(typeof(ITicker))]
public class GameTickService : MonoBehaviour,ITicker
@@ -48,6 +52,11 @@ namespace BITKit
void ITicker.Add(Action action)=>Add(action);
void ITicker.Add(Action<float> action)=>Add(action);
void ITicker.Remove(Action<float> action)=>Remove(action);
public void ManualTick(float delta)
{
throw new NotImplementedException();
}
[SerializeField] private int tickRate = 32;
[SerializeField] private bool isMainThread;
[SerializeField] private bool isConcurrent;

View File

@@ -31,6 +31,11 @@ namespace BITKit
{
IntervalTickService.Remove(action, interval);
}
public void ManualTick(float delta)
{
throw new NotImplementedException();
}
}
public class IntervalTickService

View File

@@ -0,0 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit
{
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ce6e4128b8574947be2d54ac050e39c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks.Triggers;
using UnityEngine;
namespace BITKit
{
public class UnityUpdateTick:IMainTicker
{
public ulong TickCount { get; set; }
public void Add(Action action)
{
throw new NotImplementedException();
}
public void Add(Action<float> action)=>UnityTickService.UpdateTick += action;
public void Remove(Action<float> action)=>UnityTickService.UpdateTick -= action;
public void ManualTick(float delta)
{
throw new NotImplementedException();
}
}
public class UnityFixedUpdateTick:IFixedTicker
{
public ulong TickCount { get; set; }
public void Add(Action action)
{
throw new NotImplementedException();
}
public void Add(Action<float> action)=>UnityTickService.FixedUpdateTick += action;
public void Remove(Action<float> action)=>UnityTickService.FixedUpdateTick -= action;
public void ManualTick(float delta)
{
throw new NotImplementedException();
}
}
public class UnityLateUpdateTick:IAfterTicker
{
public ulong TickCount { get; set; }
public void Add(Action action)
{
throw new NotImplementedException();
}
public void Add(Action<float> action)=>UnityTickService.LateUpdateTick += action;
public void Remove(Action<float> action)=>UnityTickService.LateUpdateTick -= action;
public void ManualTick(float delta)
{
throw new NotImplementedException();
}
}
public class UnityTickService : MonoBehaviour
{
public static event Action<float> UpdateTick;
public static event Action<float> FixedUpdateTick;
public static event Action<float> LateUpdateTick;
private void Update()
{
UpdateTick?.Invoke(Time.deltaTime);
}
private void FixedUpdate()
{
FixedUpdateTick?.Invoke(Time.fixedDeltaTime);
}
private void LateUpdate()
{
LateUpdateTick?.Invoke(Time.deltaTime);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 367ff25b1ec4724449ee78ab6690785b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 35be0f5adcb418d4888dc3ced8dbb760
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 262f7e1bcff29e141bc6ea2576c1d732
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,6 +1,5 @@
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.UI;
namespace BITKit
{

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 70a19dfc836456444bfe23cd098c3ea5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 3b408c71cc3415843bca8fda6eed69a0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +1,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.InputSystem.Composites;
using UnityEngine.UIElements;
namespace BITKit.UX
@@ -93,9 +94,15 @@ namespace BITKit.UX
});
}
}
public class UXAlert : MonoBehaviourSingleton<UXAlert>
public class UXAlert : UIToolkitOverlay,IUXDialogue
{
[SerializeField] private UIDocument document;
public static UXAlert Singleton;
public UXAlert(IUXService uxService, CancellationTokenSource cancellationToken) : base(uxService, cancellationToken)
{
Singleton = this;
}
protected override string DocumentPath => "ux_global_alert";
[UXBindPath("title-label")]
private Label _titleLabel;
@@ -105,24 +112,19 @@ namespace BITKit.UX
private Button _confirmButton;
[UXBindPath("cancel-button")]
private Button _cancelButton;
private void Start()
public override async UniTask InitializeAsync()
{
destroyCancellationToken.Register(Dispose);
await base.InitializeAsync();
UXUtils.Inject(this);
Close();
}
private void Dispose()
internal async void PrintAlertMessage(AlertMessage message)
{
}
internal void PrintAlertMessage(AlertMessage message)
{
if(destroyCancellationToken.IsCancellationRequested)return;
if(CancellationToken.IsCancellationRequested)return;
BITAppForUnity.AllowCursor.AddElement(this);
await InitializeAsync();
document.rootVisualElement.SetActive(true);
_titleLabel.text = message.title;
_contextLabel.text = message.message;
@@ -150,12 +152,22 @@ namespace BITKit.UX
_confirmButton.SetActive(true);
_cancelButton.SetActive(false);
}
BITAppForUnity.AllowCursor.AddElement(this);
}
private void Close()
{
document.rootVisualElement.SetActive(false);
Dispose();
BITAppForUnity.AllowCursor.RemoveElement(this);
}
public void Show(string content, string title = "Alert", Action confirmAction = null, Action<bool> onChoose = null)
{
PrintAlertMessage(new AlertMessage()
{
title = title,
message = content,
OnConfirm = confirmAction,
OnChoice = onChoose
});
}
}
}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 47ef6611ff66d144aba7e30f8cbecb09
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 2a0f1255bd3872c449a7ce3faef8ee74
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f32aa4e4af25a9d409da57ae4bb72c8b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 7ba09e922d82abe4a817808a8f39e91b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 5dc34c310e0729b44a166514d03601b7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 9dc4856af36fd6440a4ace72cd372ef2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -6,13 +6,22 @@ using BITKit;
using UnityEngine.UIElements;
using Cysharp.Threading.Tasks;
using System.Linq;
using System.Net.Http;
using System.Text;
using UnityEngine.Serialization;
namespace BITKit.UX
{
public sealed class UXDebuger : MonoBehaviour
{
[SerializeField] private Color textColor = Color.black;
[SerializeField]private GUIStyle style;
[SerializeReference, SubclassSelector] private IReference postApi;
[SerializeField] private bool hidePostLog;
private readonly StringBuilder _logBuilder=new();
private readonly HttpClient _httpClient = new();
private void OnEnable()
{
Application.logMessageReceivedThreaded += OnLog;
@@ -21,16 +30,36 @@ namespace BITKit.UX
{
Application.logMessageReceivedThreaded -= OnLog;
}
private void OnLog(string condition, string stacktrace, LogType type)
{
_logBuilder.Append(condition);
_logBuilder.AppendLine(condition);
if (type is LogType.Error or LogType.Exception)
{
_logBuilder.AppendLine(stacktrace);
}
if (string.IsNullOrEmpty(postApi?.Value) is false)
{
try
{
_httpClient.PostAsync(postApi.Value, new StringContent(_logBuilder.ToString())).AsUniTask()
.Forget();
}
catch (Exception)
{
if (hidePostLog) return;
throw;
}
}
}
private void OnGUI()
{
GUILayout.BeginArea(new Rect(0, 0, Screen.width, Screen.height));
GUILayout.BeginArea(new Rect(120, 120, Screen.width, Screen.height));
GUILayout.BeginVertical();
GUILayout.Label(_logBuilder.ToString());
//颜色更改为黑色
GUI.color = textColor;
GUILayout.Label(_logBuilder.ToString(),style);
GUILayout.EndVertical();
GUILayout.EndArea();
}

View File

@@ -0,0 +1,19 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.OnScreen;
using UnityEngine.UIElements;
namespace BITKit.UX
{
public class UXInputAction:OnScreenControl
{
public UXInputAction(VisualElement visualElement,string controlPathInternal)
{
this.controlPathInternal = controlPathInternal;
}
protected sealed override string controlPathInternal { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 30cd0809f33228643861548780b80b61
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1b2a8253eaf9b1b48bed89de7ff99242
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -15,10 +15,21 @@ using UnityEngine.UIElements;
namespace BITKit.UX
{
public class UXModService : MonoBehaviour
public class UXModService:UIToolKitPanel,IDisposable
{
[SerializeField] private UIDocument document;
[SerializeField] private VisualTreeAsset modTemplate;
protected override string DocumentPath => "ux_mod_Service";
private const string TemplatePath = "ux_mod_service_template";
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;
[UXBindPath("open-mod-button")]
private Button _openModButton;
@@ -31,33 +42,18 @@ namespace BITKit.UX
[UXBindPath("mod-description-label")]
private Label _modDescriptionLabel;
[UXBindPath("reload-mod-button",true)]
private Button reloadModButton;
private Button _reloadModButton;
private readonly ConcurrentDictionary<string,VisualElement> _modContainers=new();
private void OnEnable()
{
ModService.OnModInstalled+=OnModInstalled;
ModService.OnModUnInstalled+=OnModUnInstalled;
ModService.OnModLoaded+=OnModLoaded;
ModService.OnModUnLoaded+=OnModUnLoaded;
ModService.OnLocked+=OnLocked;
}
private void OnDisable()
{
ModService.OnModInstalled-=OnModInstalled;
ModService.OnModUnInstalled-=OnModUnInstalled;
ModService.OnModLoaded-=OnModLoaded;
ModService.OnModUnLoaded-=OnModUnLoaded;
ModService.OnLocked-=OnLocked;
}
private void OnLocked(bool obj)
{
document.rootVisualElement.SetEnabled(!obj);
RootVisualElement?.SetEnabled(!obj);
}
private void Start()
public override async UniTask EntryAsync()
{
await base.EntryAsync();
_modTemplate =await ModService.LoadAsset<VisualTreeAsset>(TemplatePath);
UXUtils.Inject(this);
if (_openModButton is not null)
{
@@ -66,7 +62,7 @@ namespace BITKit.UX
if (_returnButton is not null)
{
_returnButton.clicked += UxService.Return;
_returnButton.clicked += UXService.Return;
}
_modsContainer.Clear();
@@ -75,24 +71,18 @@ namespace BITKit.UX
OnModInstalled(x);
}
if (reloadModButton is not null)
reloadModButton.clicked += async () =>
if (_reloadModButton is not null)
_reloadModButton.clicked += async () =>
{
reloadModButton.SetEnabled(false);
_reloadModButton.SetEnabled(false);
await ModService.Reload();
if (destroyCancellationToken.IsCancellationRequested)
return;
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested)
return;
reloadModButton.SetEnabled(true);
_reloadModButton.SetEnabled(true);
};
}
private async void OnModUnInstalled(IMod obj)
{
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested) return;
_modContainers.TryRemove(obj.Name, out var container);
container.RemoveFromHierarchy();
}
@@ -100,7 +90,6 @@ namespace BITKit.UX
private async void OnModInstalled(IMod obj)
{
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested) return;
var container = _modContainers.GetOrAdd(obj.Name,_=> Create(obj));
container.RegisterCallback<MouseDownEvent>(x =>
{
@@ -115,7 +104,6 @@ namespace BITKit.UX
private async void OnModUnLoaded(IMod obj)
{
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested) return;
//var container = _modContainers.GetOrAdd(obj.Name,_=> Create(obj));
if(_modContainers.TryGetValue(obj.Name,out var container))
{
@@ -126,7 +114,6 @@ namespace BITKit.UX
private async void OnModLoaded(IMod obj)
{
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested) return;
var container = _modContainers.GetOrAdd(obj.Name,_=> Create(obj));
container.Get<Toggle>().SetValueWithoutNotify(true);
}
@@ -204,7 +191,7 @@ namespace BITKit.UX
}
private VisualElement Create(IMod mod)
{
var container =_modsContainer.Create(modTemplate);
var container =_modsContainer.Create(_modTemplate);
container.Get<Toggle>().RegisterValueChangedCallback(evt =>
{
if (evt.newValue)
@@ -225,6 +212,15 @@ namespace BITKit.UX
};
return container;
}
public void Dispose()
{
ModService.OnModInstalled-=OnModInstalled;
ModService.OnModUnInstalled-=OnModUnInstalled;
ModService.OnModLoaded-=OnModLoaded;
ModService.OnModUnLoaded-=OnModUnLoaded;
ModService.OnLocked-=OnLocked;
}
}
}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d0757adba9accdb4caf57436d2f5ba31
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 8127b9701e668c549abd4e3c131168ce
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 43c9066041ede064c9620a23f1920392
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit.UX
{
[Serializable]
public class UIToolkitPanelMonoProxy : UXPanelImplement
{
[SerializeField] private GameObject monoBehaviour;
protected override IUXPanel service => monoBehaviour.GetComponent<IUXPanel>();
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 66eb43c99c2ef43439773eee1acc7676
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -2,17 +2,20 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using BITKit.Mod;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
// ReSharper disable MemberCanBeProtected.Global
// ReSharper disable ClassWithVirtualMembersNeverInherited.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
namespace BITKit.UX
{
public class UIToolKitPanel : MonoBehaviour,IUXPanel
public abstract class UIToolKitPanel : IUXPanel
{
public const string USSEntry = "transition_entry";
public const string USSEntryAsync = "transition_entry_async";
@@ -20,146 +23,96 @@ namespace BITKit.UX
public const string USSExit = "transition_exit";
public const string USSExitAsync = "transition_exit_async";
public const string USSExited = "transition_exited";
[RuntimeInitializeOnLoadMethod]
private static void Reload()
{
InputActionGroup = new InputActionGroup
{
allowGlobalActivation = false,
Source = nameof(UIToolKitPanel)
};
InputActionGroup.allowInput.AddElement(0);
}
public UIToolKitPanel()
{
Index = GetType().FullName;
}
[Header(Constant.Header.Components)]
[SerializeField] protected UIDocument document;
[Header(Constant.Header.Settings)]
[SerializeField] private bool isWindow;
[SerializeField] private bool closeWhenClickOutside;
[SerializeField] private bool isAnimate;
[SerializeField] private bool allowCursor;
[SerializeField] private bool allowInput;
protected readonly IUXService UXService;
protected abstract string DocumentPath { get; }
public VisualElement RootVisualElement { get; set; }
protected VisualTreeAsset VisualTreeAsset { get; private set; }
protected UIToolKitPanel(IUXService uxService)
{
UXService = uxService;
uxService.Register(this);
}
[Header(Constant.Header.Settings)]
[SerializeField] private Optional<float> entryDuration;
[SerializeField] private Optional<float> exitDuration;
protected static InputActionGroup InputActionGroup = new()
protected virtual Optional<float> EntryDuration { get; }= new();
protected virtual Optional<float> ExitDuration { get; }= new();
protected static readonly InputActionGroup InputActionGroup = new()
{
allowGlobalActivation = false,
Source = nameof(UIToolKitPanel)
};
public bool IsWindow => isWindow;
public string Index { get; private set; }
public bool AllowCursor => allowCursor;
public bool AllowInput => allowInput;
protected float TargetOpacity { get; private set; }
protected virtual VisualElement background => document.rootVisualElement;
// protected float CurrentOpacity
// {
// get => background?.GetOpacity() ?? currentOpacity;
// set
// {
// currentOpacity = value;
// background?.SetOpacity(value);
// }
// }
protected virtual void Awake()
{
Index= typeof(UIToolKitPanel) == GetType() ? gameObject.name : GetType().Name;
document.rootVisualElement.SetActive(false);
//background?.SetOpacity(0);
if (IsWindow) document.sortingOrder++;
}
protected virtual void Start()
{
UXUtils.Inject(this);
document.rootVisualElement.AddToClassList(USSEntry);
UxService.Register(this);
destroyCancellationToken.Register(() => { UxService.UnRegister(this); });
var returnButton = document.rootVisualElement.Q("return-button");
returnButton?.RegisterCallback<MouseDownEvent>(x =>
{
if (x.button is 0)
OnReturn();
});
var invisible = document.rootVisualElement.Create<VisualElement>();
invisible.name = "invisible_return_generate";
invisible.style.position = Position.Absolute;
invisible.pickingMode = PickingMode.Ignore;
invisible.style.left = 0;
invisible.style.right = 0;
invisible.style.top = 0;
invisible.style.bottom = 0;
invisible.SendToBack();
if (closeWhenClickOutside)
{
invisible.RegisterCallback<MouseDownEvent>(x => { OnReturn(); });
invisible.pickingMode = PickingMode.Position;
}
if (isWindow)
{
invisible.style.backgroundColor = new Color(0, 0, 0, 0.9f);
}
}
public virtual bool CloseWhenClickOutside { get;}
public virtual bool IsWindow { get; }
public virtual string Index => GetType().Name;
public virtual bool AllowReload { get; }
public virtual bool AllowCursor { get; }
public virtual bool AllowInput { get; }
public bool IsEntered { get; set; }
[BIT]
public void Entry()
{
UxService.Entry(this);
}
protected virtual void OnReturn()
{
UxService.Return();
UXService.Return();
}
protected virtual void OnEnable(){}
protected virtual void OnDisable(){}
protected virtual void OnPanelEntry(){}
protected virtual void OnPanelExit(){}
void IEntryElement.Entry()
{
try
{
document.rootVisualElement.SetActive(true);
OnEntry?.Invoke();
}
catch (Exception e)
{
Debug.Log(gameObject.name);
throw;
}
}
void IEntryElement.Entry()
{
InputActionGroup.allowInput.AddElement(this);
OnEntry?.Invoke();
}
async UniTask IEntryElement.EntryAsync()
{
document.rootVisualElement.AddToClassList(USSEntry);
document.rootVisualElement.AddToClassList(USSEntryAsync);
if (RootVisualElement is null)
{
VisualTreeAsset = await ModService.LoadAsset<VisualTreeAsset>(DocumentPath);
RootVisualElement = UXService.Root.As<VisualElement>().Create(VisualTreeAsset);
RootVisualElement.pickingMode = PickingMode.Ignore;
RootVisualElement.style.position = Position.Absolute;
RootVisualElement.style.left = 0;
RootVisualElement.style.right = 0;
RootVisualElement.style.top = 0;
RootVisualElement.style.bottom = 0;
if (entryDuration.Allow)
var invisible = RootVisualElement.Create<VisualElement>();
invisible.name = "invisible_return_generate";
invisible.style.position = Position.Absolute;
invisible.pickingMode = PickingMode.Ignore;
invisible.style.left = 0;
invisible.style.right = 0;
invisible.style.top = 0;
invisible.style.bottom = 0;
invisible.SendToBack();
if (CloseWhenClickOutside)
{
invisible.RegisterCallback<MouseDownEvent>(x => { OnReturn(); });
invisible.pickingMode = PickingMode.Position;
}
if (IsWindow)
{
invisible.style.backgroundColor = new Color(0, 0, 0, 0.9f);
}
UXUtils.Inject(this);
}
RootVisualElement.SetActive(true);
RootVisualElement.AddToClassList(USSEntry);
RootVisualElement.AddToClassList(USSEntryAsync);
if (EntryDuration.Allow)
{
var task = EntryAsync();
var durationTask = UniTask.Delay(TimeSpan.FromSeconds(entryDuration.Value), cancellationToken: destroyCancellationToken);
var durationTask = UniTask.Delay(TimeSpan.FromSeconds(EntryDuration.Value));
await durationTask;
document.rootVisualElement.RemoveFromClassList(USSEntry);
document.rootVisualElement.RemoveFromClassList(USSEntryAsync);
document.rootVisualElement.AddToClassList(USSEntered);
RootVisualElement.RemoveFromClassList(USSEntry);
RootVisualElement.RemoveFromClassList(USSEntryAsync);
RootVisualElement.AddToClassList(USSEntered);
await task;
}
@@ -167,6 +120,19 @@ namespace BITKit.UX
{
await EntryAsync();
}
try
{
if (OnEntryAsync is not null)
{
await OnEntryAsync.UniTaskFunc();
}
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
}
public virtual UniTask EntryAsync()
{
@@ -175,32 +141,48 @@ namespace BITKit.UX
void IEntryElement.Entered()
{
OnPanelEntry();
OnEntryCompleted?.Invoke();
}
void IEntryElement.Exit()
{
document.rootVisualElement.AddToClassList(USSExit);
//if (IsValid is false) return;
RootVisualElement?.AddToClassList(USSExit);
OnPanelExit();
InputActionGroup.allowInput.RemoveElement(this);
OnExit?.Invoke();
}
async UniTask IEntryElement.ExitAsync()
{
document.rootVisualElement.RemoveFromClassList(USSEntered);
document.rootVisualElement.AddToClassList(USSExitAsync);
if (entryDuration.Allow is false) return;
await UniTask.Delay(TimeSpan.FromSeconds(entryDuration.Value), cancellationToken: destroyCancellationToken);
RootVisualElement?.RemoveFromClassList(USSEntered);
RootVisualElement?.AddToClassList(USSExitAsync);
await OnExitAsync.UniTaskFunc();
if (EntryDuration.Allow is false) return;
await UniTask.Delay(TimeSpan.FromSeconds(EntryDuration.Value));
}
void IEntryElement.Exited()
{
document.rootVisualElement.RemoveFromClassList(USSExit);
document.rootVisualElement.RemoveFromClassList(USSExitAsync);
document.rootVisualElement.AddToClassList(USSEntry);
document.rootVisualElement.SetActive(false);
OnExit?.Invoke();
RootVisualElement?.RemoveFromClassList(USSExit);
RootVisualElement?.RemoveFromClassList(USSExitAsync);
RootVisualElement?.AddToClassList(USSEntry);
RootVisualElement?.SetActive(false);
if (AllowReload)
{
RootVisualElement?.RemoveFromHierarchy();
RootVisualElement = null;
}
OnExitCompleted?.Invoke();
}
public event Action OnEntry;
public event Func<UniTask> OnEntryAsync;
public event Action OnEntryCompleted;
public event Action OnExit;
public virtual void OnUpdate(float deltaTime)
public event Func<UniTask> OnExitAsync;
public event Action OnExitCompleted;
public virtual void OnTick(float deltaTime)
{
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.Threading;
using BITKit.Mod;
using Cysharp.Threading.Tasks;
using UnityEngine.UIElements;
// ReSharper disable MemberCanBePrivate.Global
namespace BITKit.UX
{
public abstract class UIToolkitOverlay:IDisposable
{
protected readonly CancellationTokenSource CancellationToken;
protected readonly IUXService UXService;
protected VisualElement RootVisualElement { get; set; }
private bool _initialized;
protected UIToolkitOverlay(IUXService uxService, CancellationTokenSource cancellationToken)
{
UXService = uxService;
CancellationToken = cancellationToken;
CancellationToken.Token.Register(Dispose);
}
protected abstract string DocumentPath { get; }
// ReSharper disable once MemberCanBeProtected.Global
public virtual async UniTask InitializeAsync()
{
if(_initialized)return;
var asset =await ModService.LoadAsset<VisualTreeAsset>(DocumentPath);
var root= RootVisualElement = UXService.Root.As<VisualElement>().Create(asset);
RootVisualElement.BringToFront();
RootVisualElement.name = GetType().Name;
RootVisualElement.pickingMode = PickingMode.Ignore;
root.style.position = Position.Absolute;
root.style.top = 0;
root.style.bottom = 0;
root.style.left = 0;
root.style.right = 0;
UXUtils.Inject(this);
_initialized = true;
}
public virtual void Dispose()
{
if(RootVisualElement is null)return;
_initialized = false;
RootVisualElement.RemoveFromHierarchy();
RootVisualElement = null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e78199af4607c0d438836fd782fdf8ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,18 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit.UX
{
public class UIToolkitPanelDebuger : UIToolKitPanel
{
[SerializeField] private InputActionGroup inputActionGroup;
private void Update()
{
inputActionGroup = InputActionGroup;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2dbf277baef324944aa89bbd72966261
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
using System.Collections;
using System.Collections.Generic;
using BITKit.UX;
using UnityEngine;
public class UIToolkitSubPanel
{
public UIToolkitSubPanel()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 398253ee7f746d143bbbcd9effab9da1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,64 +1,62 @@
using System;
using System.Collections.Generic;
using System.Text;
using BITKit.Mod;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
namespace BITKit.UX
{
/// <summary>
/// 适用于Unity的UX Service
/// </summary>
public class UxService : MonoBehaviour, IUXService
public class UXService : IUXService
{
/// <summary>
/// 重新初始化,使用<see cref="RuntimeInitializeLoadType.SubsystemRegistration"/>确保在所有子系统注册后执行
/// </summary>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void Initialized()
private readonly IAfterTicker _ticker;
private readonly IServiceProvider _serviceProvider;
public UXService(IAfterTicker ticker, IServiceProvider serviceProvider)
{
RegistryQueue.Clear();
UnRegistryQueue.Clear();
Panels.Clear();
EntryQueue.Clear();
_currentPanel = null;
History.Clear();
_entryGroup = new EntryGroup<IUXPanel>();
_windowEntryGroup = new EntryGroup<IUXPanel>();
_ticker = ticker;
_serviceProvider = serviceProvider;
_entryGroup.OnEntry += OnEntry;
_ticker.Add(OnTick);
}
private static EntryGroup<IUXPanel> _entryGroup = new();
private static EntryGroup<IUXPanel> _windowEntryGroup = new();
private readonly EntryGroup<IUXPanel> _entryGroup = new();
private readonly EntryGroup<IUXPanel> _windowEntryGroup = new();
/// <summary>
/// 内部注册面板队列
/// </summary>
private static readonly Queue<IUXPanel> RegistryQueue = new();
private readonly Queue<IUXPanel> _registryQueue = new();
/// <summary>
/// 内部注销面板队列
/// </summary>
private static readonly Queue<IUXPanel> UnRegistryQueue = new();
private readonly Queue<IUXPanel> _unRegistryQueue = new();
/// <summary>
/// 已注册面板字典
/// </summary>
private static readonly Dictionary<string, IUXPanel> Panels = new();
private readonly Dictionary<string, IUXPanel> _panels = new();
/// <summary>
/// 等待启用的面板队列
/// </summary>
private static readonly Stack<IUXPanel> EntryQueue = new();
private readonly Stack<IUXPanel> _entryQueue = new();
private readonly List<string> _entryQueueByName = new();
/// <summary>
/// 返回面板缓冲区
/// </summary>
private static readonly DoubleBuffer<IUXPanel> ReturnBuffer = new();
private readonly DoubleBuffer<IUXPanel> _returnBuffer = new();
/// <summary>
/// 已启用面板
/// </summary>
private static IUXPanel _currentPanel;
private IUXPanel _currentPanel;
/// <summary>
/// 历史面板
@@ -70,13 +68,43 @@ namespace BITKit.UX
/// </summary>
public static void ClearHistory() => History.Clear();
public static void Register(IUXPanel panel) => RegistryQueue.Enqueue(panel);
public object Root { get; private set; }
public async UniTask InitializeAsync()
{
var gameObject = new GameObject("UXService");
Object.DontDestroyOnLoad(gameObject);
var document = gameObject.AddComponent<UIDocument>();
try
{
var panelSettings =await ModService.LoadAsset<PanelSettings>("ux_panel_settings");
document.panelSettings = panelSettings;
}
catch (Exception e)
{
BIT4Log.Warning<UXService>("未找到ux_panel_settings");
throw;
}
Root = document.rootVisualElement;
}
public static void UnRegister(IUXPanel panel) => UnRegistryQueue.Enqueue(panel);
public void Register(IUXPanel panel) => _registryQueue.Enqueue(panel);
public static void Entry<T>() where T : IUXPanel => EntryQueue.Push(Panels[typeof(T).Name]);
public void UnRegister(IUXPanel panel) => _unRegistryQueue.Enqueue(panel);
public static void Return()
public void Entry<T>() where T : IUXPanel
{
var panel = _serviceProvider.GetRequiredService<T>();
Entry(panel);
//Entry(typeof(T).Name);
}
public void Entry(IUXPanel panel) => _entryQueue.Push(panel);
public void Entry(string panelName) => _entryQueueByName.TryAdd(panelName);
public void Return()
{
if(_windowEntryGroup.TryGetEntried(out _))
{
@@ -85,70 +113,58 @@ namespace BITKit.UX
}
if (History.TryPop(out var returnPanel))
{
ReturnBuffer.Release(returnPanel);
_returnBuffer.Release(returnPanel);
}
}
public static void Entry(IUXPanel panel) => EntryQueue.Push(panel);
private static void Entry(string panelName) => EntryQueue.Push(Panels[panelName]);
[SerializeReference, SubclassSelector] private IUXPanel initialPanel;
[SerializeField, ReadOnly(HideLabel = true)]
private string log;
private StringBuilder _reportBuilder = new();
private bool _initialized;
private void Start()
{
_entryGroup.OnEntry += OnEntry;
_entryGroup.OnExit += OnExit;
}
private static void OnExit(IUXPanel obj)
{
//History.Push(obj);
}
private static void OnEntry(IUXPanel obj)
private void OnEntry(IUXPanel obj)
{
_currentPanel = obj;
}
private void Update()
private void OnTick(float delta)
{
try
{
while (RegistryQueue.TryDequeue(out var result))
while (_registryQueue.TryDequeue(out var result))
{
if (result is null) continue;
_reportBuilder.AppendLine(("注册面板:" + result.Index));
_entryGroup.list.Add(result);
Panels.Set(result.Index, result);
_panels.Set(result.Index, result);
}
while (UnRegistryQueue.TryDequeue(out var result))
while (_unRegistryQueue.TryDequeue(out var result))
{
if (result is null) continue;
_reportBuilder.AppendLine(("注销面板:" + result.Index));
_entryGroup.list.Remove(result);
Panels.Remove(result.Index);
_panels.Remove(result.Index);
}
if (ReturnBuffer.TryGetRelease(out var returnPanel))
if (_returnBuffer.TryGetRelease(out var returnPanel))
{
_reportBuilder.AppendLine(("返回面板:" + returnPanel.Index));
_entryGroup.Entry(x=>x.Index==returnPanel.Index);
BITAppForUnity.AllowCursor.SetElements(this, returnPanel.AllowCursor);
BITInputSystem.AllowInput.SetElements(this, returnPanel.AllowInput);
}
if (EntryQueue.TryPop(out var nextPanel))
foreach (var panelName in _entryQueueByName)
{
if (!_panels.TryGetValue(panelName, out var panel))continue;
_entryQueue.Push(panel);
_entryQueueByName.TryRemove(panelName);
break;
}
if (_entryQueue.TryPop(out var nextPanel))
{
if (nextPanel.IsWindow)
{
_reportBuilder.AppendLine(("窗口面板:" + nextPanel.Index));
_windowEntryGroup.Entry(nextPanel);
return;
}
_reportBuilder.AppendLine(("启用面板:" + nextPanel.Index));
_windowEntryGroup.Entry(-1);
History.Push(_currentPanel);
_entryGroup.Entry(x=>x.Index==nextPanel.Index);
@@ -157,36 +173,31 @@ namespace BITKit.UX
}
if (_entryGroup.TryGetEntried(out var currentPanel))
{
currentPanel.OnUpdate(Time.deltaTime);
currentPanel.OnTick(Time.deltaTime);
}
if(_windowEntryGroup.TryGetEntried(out var windowPanel))
{
windowPanel.OnUpdate(Time.deltaTime);
}
if (currentPanel is null && Panels.Count > 0)
{
Entry(initialPanel);
windowPanel.OnTick(Time.deltaTime);
}
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
log = _reportBuilder.ToString();
}
void IUXService.Register(IUXPanel panel) => Register(panel);
void IUXService.UnRegister(IUXPanel panel) => UnRegister(panel);
void IUXService.Entry<T>() => Entry<T>();
void IUXService.Return() => Return();
void IUXService.Entry(IUXPanel panel) => Entry(panel);
void IUXService.Entry(string panelName) => Entry(panelName);
public async void Dispose()
{
_ticker.Remove(OnTick);
await UniTask.SwitchToMainThread();
if (_currentPanel is not null)
{
// ReSharper disable once MethodHasAsyncOverload
_currentPanel.Exit();
await _currentPanel.ExitAsync();
_currentPanel.Exited();
}
}
}
}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1a4110ffce8eaaa4fbb4c6cc86d62f1e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1a060a5c79259eb408daf2bf3a38d8e1
guid: 951ffa58b33aefc46bb69a009983f61d
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
namespace BITKit.UX
{
public class UXToolTips:IDisposable
{
private readonly IUXService _uxService;
private readonly IMainTicker _ticker;
public UXToolTips(IUXService uxService, IMainTicker ticker)
{
_uxService = uxService;
_ticker = ticker;
_ticker.Add(OnTick);
}
private VisualElement _rootVisualElement;
private Label _label;
public void Dispose()
{
_ticker.Remove(OnTick);
}
private void OnTick(float obj)
{
if (_label is null && _uxService.Root is not null)
{
_rootVisualElement=_uxService.Root as VisualElement;
_label = _rootVisualElement.Create<Label>();
_label.AddToClassList("bitkit-tool-tips");
_label.style.position = Position.Absolute;
}
if(_label is null || _rootVisualElement is null)return;
var tooltip = CurrentToolTip(_rootVisualElement.panel);
if (tooltip != "")
{
var mouse = Mouse.current;
if (mouse is null) return;
var mousePos = mouse.position.ReadValue();
mousePos.y = Screen.height - mousePos.y;
var pos =RuntimePanelUtils.ScreenToPanel(_label.panel,mousePos);
pos.x += 24;
if (pos.x + _label.layout.width > _label.panel.visualTree.layout.width)
{
//pos.x = label.panel.visualTree.layout.width - label.layout.width - label.layout.width;
pos.x-=_label.layout.width+48;
}
_label.visible = true;
_label.text = tooltip;
_label.transform.position = pos;
_label.BringToFront();
}
else
{
_label.visible = false;
}
}
private string CurrentToolTip(IPanel panel)
{
// https://docs.unity3d.com/2022.2/Documentation/Manual/UIE-faq-event-and-input-system.html
if (!EventSystem.current.IsPointerOverGameObject()) return "";
var screenPosition = Mouse.current.position.ReadValue();
screenPosition.y = Screen.height - screenPosition.y;
VisualElement ve = panel.Pick(RuntimePanelUtils.ScreenToPanel(panel, screenPosition));
return ve == null ? "" : ve.tooltip;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac89bede6edc4874380395982ecc8af8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More