iFactory.Cutting.Unity/Assets/BITKit/Unity/Scripts/UX/ModService/UXModService.cs

221 lines
5.5 KiB
C#
Raw Normal View History

2024-01-23 02:56:26 +08:00
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
2024-03-04 18:45:21 +08:00
using System.Reflection;
2024-01-23 02:56:26 +08:00
using System.Threading;
using AnotherFileBrowser.Windows;
using BITKit.Mod;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit.UX
{
public class UXModService : MonoBehaviour
{
[SerializeField] private UIDocument document;
[SerializeField] private VisualTreeAsset modTemplate;
[UXBindPath("open-mod-button")]
private Button _openModButton;
[UXBindPath("mods-container")]
private VisualElement _modsContainer;
[UXBindPath("return-button")]
private Button _returnButton;
[UXBindPath("mod-name-label")]
private Label _modNameLabel;
[UXBindPath("mod-description-label")]
private Label _modDescriptionLabel;
2024-03-04 18:45:21 +08:00
[UXBindPath("reload-mod-button",true)]
private Button reloadModButton;
2024-01-23 02:56:26 +08:00
private readonly ConcurrentDictionary<string,UXContainer> _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);
}
2024-03-04 18:45:21 +08:00
2024-01-23 02:56:26 +08:00
private void Start()
{
UXUtils.Inject(this);
if (_openModButton is not null)
{
_openModButton.clicked += OpenMod;
}
2024-03-04 18:45:21 +08:00
2024-01-23 02:56:26 +08:00
if (_returnButton is not null)
{
_returnButton.clicked += UXService.Return;
}
2024-03-04 18:45:21 +08:00
2024-01-23 02:56:26 +08:00
_modsContainer.Clear();
foreach (var x in ModService.Mods)
{
OnModInstalled(x);
}
2024-03-04 18:45:21 +08:00
if (reloadModButton is not null)
reloadModButton.clicked += async () =>
{
reloadModButton.SetEnabled(false);
await ModService.Reload();
if (destroyCancellationToken.IsCancellationRequested)
return;
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested)
return;
reloadModButton.SetEnabled(true);
};
2024-01-23 02:56:26 +08:00
}
private async void OnModUnInstalled(IMod obj)
{
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested) return;
_modContainers.TryRemove(obj.Name, out var container);
2024-03-04 18:45:21 +08:00
container.visualElement.RemoveFromHierarchy();
2024-01-23 02:56:26 +08:00
}
private async void OnModInstalled(IMod obj)
{
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested) return;
_modContainers.GetOrAdd(obj.Name,_=> Create(obj));
}
private async void OnModUnLoaded(IMod obj)
{
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested) return;
var container = _modContainers.GetOrAdd(obj.Name,_=> Create(obj));
container.toggle.SetValueWithoutNotify(false);
}
private async void OnModLoaded(IMod obj)
{
await UniTask.SwitchToMainThread();
if (destroyCancellationToken.IsCancellationRequested) return;
var container = _modContainers.GetOrAdd(obj.Name,_=> Create(obj));
container.toggle.SetValueWithoutNotify(true);
}
private static void OpenMod()
{
2024-03-04 18:45:21 +08:00
BIT4Log.Log("正在打开选择文件对话框");
#if UNITY_EDITOR
2024-01-23 02:56:26 +08:00
new Thread(OpenModInternal).Start();
2024-03-04 18:45:21 +08:00
#else
OpenModInternal();
#endif
2024-01-23 02:56:26 +08:00
return;
void OpenModInternal()
{
2024-03-04 18:45:21 +08:00
BIT4Log.Log<UXModService>("已进入文件对话框线程");
2024-01-23 02:56:26 +08:00
new FileBrowser().OpenFileBrowser(new BrowserProperties()
{
2024-03-04 18:45:21 +08:00
//filterIndex = 0,
//filter = "C Sharp files (*.cs)|*.cs |Dll files (*.dll)|*.dll",
2024-01-23 02:56:26 +08:00
}, Filepath);
return;
async void Filepath(string path)
{
2024-03-04 18:45:21 +08:00
BIT4Log.Log<UXModService>("已选择文件:"+path);
2024-01-23 02:56:26 +08:00
await BITApp.SwitchToMainThread();
2024-03-04 18:45:21 +08:00
try
{
var file = new FileInfo(path);
switch (file.Extension)
{
case ".cs":
var code = await File.ReadAllTextAsync(path);
var assembly = BITSharp.Compile(code);
await ModService.Load(assembly,Path.GetDirectoryName(path));
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)
2024-01-23 02:56:26 +08:00
{
2024-03-04 18:45:21 +08:00
Alert.Print(new AlertMessage()
{
title = "加载失败",
message = e.Message
});
BIT4Log.LogException(e);
2024-01-23 02:56:26 +08:00
}
}
}
}
private UXContainer Create(IMod mod)
{
var container = new UXContainer(_modsContainer.Create(modTemplate))
{
titleLabel =
{
text = mod.Name
},
descriptionLabel =
{
text = mod.Description
}
};
container.toggle.RegisterValueChangedCallback(evt =>
{
if (evt.newValue)
{
ModService.Load(mod);
}
else
{
ModService.UnLoad(mod);
}
});
container.visualElement.tooltip = mod.Name+"\n"+mod.Description;
container.button.clicked += () =>
{
_modNameLabel.text = mod.Name;
_modDescriptionLabel.text = mod.Description;
};
return container;
}
}
}