268 lines
9.0 KiB
C#
268 lines
9.0 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using BITKit;
|
|
using BITKit.Entities;
|
|
using BITKit.StateMachine;
|
|
using BITKit.UX;
|
|
using Cysharp.Threading.Tasks;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Net.Project.B.Inventory;
|
|
using Net.Project.B.Item;
|
|
using Project.B.Entities;
|
|
using Project.B.Item;
|
|
using Project.B.Player;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.InputSystem.XR.Haptics;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace Net.Project.B.PDA
|
|
{
|
|
[Serializable]
|
|
public struct AppControllerClass : IScriptableControllerClass
|
|
{
|
|
|
|
}
|
|
public class UnityPDAService:UIToolKitPanel, IPDAService
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly IManagedItemService _managedItemService;
|
|
private readonly IUXKeyMap<InputAction> _uxKeyMap;
|
|
protected override string DocumentPath => "ui_pda";
|
|
public override bool AllowCursor => true;
|
|
public override bool CloseWhenClickOutside => true;
|
|
[UXBindPath("pda-container")] private VisualElement _pdaContainer;
|
|
[UXBindPath("dock-container")] private VisualElement _dockContainer;
|
|
[UXBindPath("app-container")] private VisualElement _appContainer;
|
|
[UXBindPath("home-button")] private Button _homeButton;
|
|
|
|
[Inject]
|
|
private IPlayerWeaponInventory _playerWeaponInventory;
|
|
|
|
[Inject] private IPlayerInventory _playerInventory;
|
|
|
|
private readonly HashSet<int> _pdaItems = new();
|
|
|
|
private VisualTreeAsset _appTemplate;
|
|
|
|
private readonly Dictionary<string,IAppClass> _routes = new();
|
|
|
|
private CancellationTokenSource _operatorCts = new();
|
|
private readonly ValidHandle _operatorHandle = new();
|
|
|
|
private readonly HashSet<object> _initiated = new();
|
|
|
|
private readonly Dictionary<string, VisualElement> _appLaunchers = new();
|
|
|
|
private IAppClass _currentAppClass;
|
|
private string _currentUrl;
|
|
|
|
public UnityPDAService(IUXService uxService, IPlayerFactory playerFactory, IEntitiesService entitiesService, IManagedItemService managedItemService, IUXKeyMap<InputAction> uxKeyMap, IServiceProvider serviceProvider) : base(uxService)
|
|
{
|
|
_managedItemService = managedItemService;
|
|
_uxKeyMap = uxKeyMap;
|
|
_serviceProvider = serviceProvider;
|
|
|
|
playerFactory.OnEntityCreated += OnEntityCreated;
|
|
|
|
foreach (var scriptableItem in entitiesService.QueryComponents<ScriptableItem>())
|
|
{
|
|
if (scriptableItem.ControllerClass is AppControllerClass)
|
|
{
|
|
_pdaItems.Add(scriptableItem.Id);
|
|
}
|
|
}
|
|
|
|
OnInitiatedAsync += InitiatedAsync;
|
|
|
|
foreach (var appClass in _serviceProvider.GetServices<IAppClass>())
|
|
{
|
|
foreach (var path in appClass.Routes)
|
|
{
|
|
_routes.Add(path,appClass);
|
|
}
|
|
}
|
|
}
|
|
|
|
private UniTask InitiatedAsync()
|
|
{
|
|
_appTemplate = _appContainer.Q<TemplateContainer>().templateSource;
|
|
_appContainer.Clear();
|
|
|
|
foreach (var appClass in _serviceProvider.GetServices<IAppClass>())
|
|
{
|
|
var app = (IApp)Activator.CreateInstance(appClass.AppType);
|
|
|
|
var container = _appContainer.Create(_appTemplate);
|
|
container.Get<Label>().text = app.AppName;
|
|
|
|
container.Get<VisualElement>().AddToClassList(app.PackageName.Replace(".", "-"));
|
|
|
|
container.Get<Button>().clicked += () =>
|
|
{
|
|
container.RemoveFromClassList("allow-badge");
|
|
var type = typeof(IAppClass<>).MakeGenericType(app.GetType());
|
|
var service = (IAppClass)_serviceProvider.GetRequiredService(type);
|
|
Navigate(service!.Routes[0]).Forget();
|
|
};
|
|
|
|
var packageName = Activator.CreateInstance(appClass.AppType).As<IApp>().PackageName;
|
|
|
|
_appLaunchers[packageName] = container;
|
|
}
|
|
|
|
_homeButton.clicked += ()=>Home().Forget();
|
|
|
|
#if UNITY_STANDALONE_WIN
|
|
var wallpaperPath = GetWindowsWallPaper.GetWallpaperPath();
|
|
|
|
if (System.IO.File.Exists(wallpaperPath))
|
|
{
|
|
byte[] imageData = System.IO.File.ReadAllBytes(wallpaperPath);
|
|
Texture2D texture = new Texture2D(2, 2);
|
|
if (texture.LoadImage(imageData))
|
|
{
|
|
RootVisualElement.Get<VisualElement>().style.backgroundImage = new StyleBackground(texture);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
protected override void OnPanelEntry()
|
|
{
|
|
base.OnPanelEntry();
|
|
InputActionGroup.RegisterCallback(_uxKeyMap.CancelKey, OnCancel);
|
|
InputActionGroup.RegisterCallback(_uxKeyMap.InventoryKey, OnCancel);
|
|
}
|
|
|
|
private void OnCancel(InputAction.CallbackContext obj)
|
|
{
|
|
if (obj.JustPressed())
|
|
{
|
|
OnReturn();
|
|
}
|
|
}
|
|
|
|
protected override void OnPanelExit()
|
|
{
|
|
base.OnPanelExit();
|
|
InputActionGroup.UnRegisterCallback(_uxKeyMap.CancelKey, OnCancel);
|
|
InputActionGroup.UnRegisterCallback(_uxKeyMap.InventoryKey, OnCancel);
|
|
}
|
|
|
|
private UniTask OnEntityCreated(string arg1, IEntity arg2)
|
|
{
|
|
arg2.Inject(this);
|
|
|
|
_playerWeaponInventory.StateMachine.OnStateChanged += OnStateChanged;
|
|
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
private void OnStateChanged(IPlayerWeaponController arg1, IPlayerWeaponController arg2)
|
|
{
|
|
if(arg2 is null)return;
|
|
if(_managedItemService.Items.TryGetValue(arg2.Identifier,out var item) is false && _playerInventory.Container.ItemDictionary.TryGetValue(arg2.Identifier,out item) is false)return;
|
|
if(_pdaItems.Contains(item.ScriptableId) is false)return;
|
|
UXService.Entry(this);
|
|
}
|
|
public async UniTask Navigate(string url)
|
|
{
|
|
_operatorCts.Cancel();
|
|
_operatorCts = new();
|
|
|
|
await _operatorHandle;
|
|
using var _ = _operatorHandle.GetHandle();
|
|
|
|
if (_routes.TryGetValue(url, out var appClass) is false)return;
|
|
|
|
var prevClass = _currentAppClass;
|
|
|
|
if (prevClass is not null)
|
|
{
|
|
prevClass.Enabled = false;
|
|
await prevClass.OnStateExitAsync(prevClass,appClass);
|
|
prevClass.OnStateExit(prevClass,appClass);
|
|
}
|
|
|
|
if(_operatorCts.IsCancellationRequested)return;
|
|
|
|
_currentAppClass = appClass;
|
|
|
|
if (_initiated.Add(appClass))
|
|
{
|
|
await appClass.InitializeAsync();
|
|
appClass.Initialize();
|
|
}
|
|
|
|
appClass.Enabled = true;
|
|
|
|
var prevUrl = _currentUrl;
|
|
|
|
var page=await appClass.GetPage(_currentUrl = url);
|
|
if (page is VisualElement visualElement)
|
|
{
|
|
_pdaContainer.Add(visualElement);
|
|
}
|
|
|
|
appClass.OnStateEntryAsync(prevClass);
|
|
appClass.OnStateEntry(prevClass);
|
|
|
|
await OnNavigatedAsync.UniTaskFunc(prevUrl, url);
|
|
OnNavigated?.Invoke(prevUrl,url);
|
|
}
|
|
public async UniTask Home()
|
|
{
|
|
|
|
_operatorCts.Cancel();
|
|
_operatorCts = new();
|
|
|
|
await _operatorHandle;
|
|
using var _ = _operatorHandle.GetHandle();
|
|
|
|
if (_currentAppClass is not null)
|
|
{
|
|
_currentAppClass.Enabled = false;
|
|
|
|
await _currentAppClass.OnStateExitAsync(_currentAppClass,null);
|
|
_currentAppClass.OnStateExit(_currentAppClass,null);
|
|
|
|
_currentAppClass = null;
|
|
}
|
|
|
|
_pdaContainer.Clear();
|
|
}
|
|
public async UniTask Back()
|
|
{
|
|
_operatorCts.Cancel();
|
|
_operatorCts = new();
|
|
|
|
await _operatorHandle;
|
|
using var _ = _operatorHandle.GetHandle();
|
|
}
|
|
|
|
public void Badge(string packageName)
|
|
{
|
|
if (_currentAppClass is not null)
|
|
{
|
|
var app = Activator.CreateInstance(_currentAppClass.AppType).As<IApp>().PackageName;
|
|
if(string.Equals(app,packageName))return;
|
|
}
|
|
_appLaunchers[packageName].AddToClassList("allow-badge");
|
|
}
|
|
|
|
public event Action<string, string> OnNavigated;
|
|
public event Func<string, string, UniTask> OnNavigatedAsync;
|
|
public event Action<string> OnNotification;
|
|
public void Notify(string message)
|
|
{
|
|
OnNotification?.Invoke(message);
|
|
}
|
|
}
|
|
}
|