using System; using System.Collections; using System.Collections.Generic; using BITKit; using BITKit.Mod; using BITKit.UX; using BITKit.WorldNode; using Cysharp.Threading.Tasks; using Net.Project.B.Interaction; using Net.Project.B.Quest; using Project.B.Map; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; namespace Net.Like.Xue.Tokyo.UX { public class UXHud : UIToolKitPanel { private readonly IGameMapService _gameMapService; private readonly IWorldInteractionService _interactionService; private readonly WorldInfoNodeService _worldInfoNodeService; private readonly IQuestService _questService; public UXHud(IUXService uxService, IGameMapService gameMapService, IWorldInteractionService interactionService, WorldInfoNodeService worldInfoNodeService, IQuestService questService) : base(uxService) { _gameMapService = gameMapService; _interactionService = interactionService; _worldInfoNodeService = worldInfoNodeService; _questService = questService; _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)); } } private void OnInteraction(object arg1, IWorldInteractable arg2, WorldInteractionProcess arg3, object arg4) { switch (arg3) { case WorldInteractionProcess.Hover: _interactionTips.SetActive(true); _interactionTips.text = _worldInfoNodeService.WorldInfoNodes.TryGetValue(arg2.Id, out var node) ? node.Name : "互动"; 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("minimap-container")] private VisualElement _minimapContainer; [UXBindPath("minimap-player")] private VisualElement _miniPlayer; [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(); public override async UniTask EntryAsync() { await base.EntryAsync(); UXUtils.Inject(this); _interactionTips.SetActive(false); _minimapContainer.RegisterCallback(x => { UXService.Entry(); }); _timeSlider.RegisterValueChangedCallback(x => { Data.Set("Time", x.newValue); }); _questContainer.Clear(); _questTemplate =await ModService.LoadAsset("ux_quest_template"); _timeSlider.value = Data.Get("Time"); } public override void OnTick(float deltaTime) { base.OnTick(deltaTime); if(RootVisualElement is null)return; if (!_minimapCamera) { _minimapCamera = GameObject.Find("minimap_camera")?.GetComponent(); return; } if (!_mainCamera) { _mainCamera = Camera.main; return; } var point = _minimapCamera.WorldToViewportPoint(_mainCamera.transform.position); _miniPlayer.style.left = _minimapContainer.layout.width * point.x - _miniPlayer.layout.width / 2; _miniPlayer.style.top = _minimapContainer.layout.height * (1-point.y) - _miniPlayer.layout.height / 2; if (_questContainer is not null && _questTemplate!=null) { while (_questQueue.TryDequeue(out var quest)) { var visualElement = _questContainer.Create(_questTemplate); visualElement.Get