using System; using System.Collections; using System.Collections.Generic; using BITKit; using BITKit.Entities; using BITKit.Mod; using BITKit.UX; using BITKit.UX.Hotkey; using BITKit.WorldNode; using Cysharp.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Net.Project.B.Emoji; using Net.Project.B.Interaction; using Net.Project.B.Quest; using Net.Project.B.UX; using Project.B.Entities; using Project.B.Map; using UnityEditor; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UIElements; namespace Net.Like.Xue.Tokyo.UX { public class UXHud : UIToolKitPanel { private readonly IEntitiesService _entitiesService; private readonly IPlayerFactory _playerFactory; private readonly IGameMapService _gameMapService; private readonly IWorldInteractionService _interactionService; private readonly IQuestService _questService; private readonly UXRadialMenu _radialMenu; [Inject] private IEmojiService _emojiService; public UXHud(IUXService uxService, IGameMapService gameMapService, IWorldInteractionService interactionService, IQuestService questService, UXRadialMenu radialMenu, IPlayerFactory playerFactory, IEntitiesService entitiesService) : base(uxService) { _gameMapService = gameMapService; _interactionService = interactionService; _questService = questService; _radialMenu = radialMenu; _playerFactory = playerFactory; _entitiesService = entitiesService; _gameMapService.OnMapChanged += OnMapChanged; _interactionService.OnInteraction += OnInteraction; Data.AddListener("Time",x=> { _timeSlider?.SetValueWithoutNotify(x); }); _questService.OnQuestCreatedOrUpdated +=(x,y,z)=>_questQueue.Enqueue(new(x,y,z)); foreach (var (index,quest) in _questService.Quests) { _questQueue.Enqueue(new(quest,QuestState.Inactive,quest.CurrentState)); } _playerFactory.OnEntityCreated += OnEntityCreated; } private UniTask OnEntityCreated(string arg1, IEntity arg2) { arg2.Inject(this); return UniTask.CompletedTask; } private void OnInteraction(object arg1, IWorldInteractable arg2, WorldInteractionProcess arg3, object arg4) { switch (arg3) { case WorldInteractionProcess.Hover: _interactionTips.SetActive(true); if (_entitiesService.Entities.TryGetValue(arg2.Id, out var entity) && entity.ServiceProvider.GetService() is { } infoNode && string.IsNullOrEmpty(infoNode.Name) is false) { _interactionTips.text = infoNode.Name; } else { _interactionTips.text = "互动"; } break; default: _interactionTips.SetActive(false); break; } } private void OnMapChanged(Guid arg1, string arg2) { UXService.Entry(); } protected override string DocumentPath => "ux_hud"; public override bool AllowInput => true; public override bool AllowCursor => false; [UXBindPath("interaction-tips")] private Label _interactionTips; [UXBindPath("time-slider")] private Slider _timeSlider; [UXBindPath("quest-container")] private VisualElement _questContainer; private Camera _minimapCamera; private Camera _mainCamera; private VisualTreeAsset _questTemplate; private readonly Queue<(IQuestData questData, QuestState oldQuestState, QuestState newQuestState)> _questQueue = new(); private readonly Dictionary _questContainers = new(); public override async UniTask EntryAsync() { await base.EntryAsync(); UXUtils.Inject(this); _interactionTips.SetActive(false); _timeSlider.RegisterValueChangedCallback(x => { Data.Set("Time", x.newValue); }); _questContainer.Clear(); _questTemplate =await ModService.LoadAsset("ux_quest_template"); _timeSlider.value = Data.Get("Time"); } public override async void OnTick(float deltaTime) { base.OnTick(deltaTime); if(RootVisualElement is null)return; if (Keyboard.current is { capsLockKey: { wasPressedThisFrame: true } } or {mKey:{wasPressedThisFrame:true}}) { UXService.Entry(); }else if (Keyboard.current is { f1Key: { wasPressedThisFrame: true } }) { var collection = new HotkeyCollection(); _radialMenu.HotkeyCollection = collection; foreach (var emojiData in await _emojiService.GetAllEmojis()) { collection.Register(new HotkeyProvider() { Name = emojiData.Name, Description = emojiData.Description, Enabled = true, OnPerform = () => _emojiService.Play(emojiData), }); } UXService.Entry(_radialMenu); }else if (Keyboard.current is { tabKey: { wasPressedThisFrame: true } }) { UXService.Entry(); } if (_questContainer is not null && _questTemplate!=null) { while (_questQueue.TryDequeue(out var quest)) { if (quest.questData.IsCompleted) { if (_questContainers.TryGetValue(quest.questData.Identity, out var visualElement)) { visualElement.RemoveFromHierarchy(); } } else { var visualElement = _questContainer.Create(_questTemplate); visualElement.Get