using System.Collections; using System.Collections.Generic; using System.Linq; using BITFALL.Hotkey; using BITKit; using BITKit.Entities; using BITKit.Entities.Player; using BITKit.UX; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Interactions; using UnityEngine.UIElements; namespace BITFALL.UX { public class UXRadialMenu : UIToolKitPanel { [SerializeReference, SubclassSelector] private IPlayerService playerService; [SerializeField] private InputActionReference escapeAction; [SerializeField] private InputActionReference radialMenuAction; [SerializeField] private InputActionReference cancelAction; [SerializeField] private VisualTreeAsset template; [UXBindPath("radialMenu-container")] private VisualElement _container; [UXBindPath("info-label")] private Label infoLabel; [Inject] private IHotkeyCollection _hotkeyCollection; private IHotkeyProvider _currentHotkeyProvider; private VisualElement _currentHotkeyDuration; protected override void Start() { base.Start(); BITKit.UX.UXUtils.Inject(this); _container.Clear(); playerService.OnPlayerInitialized += OnPlayerInitialized; playerService.OnPlayerDisposed += OnPlayerDisposed; } private void OnPlayerDisposed(Entity obj) { _hotkeyCollection = null; if(IsEntered)UXService.Return(); } private void OnPlayerInitialized(Entity obj) { obj.Inject(this); } private static void OnEscape(InputAction.CallbackContext obj) { if (obj is { interaction: PressInteraction, performed: true }) UXService.Entry(); } public override void OnUpdate(float deltaTime) { base.OnUpdate(deltaTime); if (IsEntered is false) return; if (_currentHotkeyProvider is not null) { var width = Mathf.Clamp(_currentHotkeyDuration.style.width.value.value + 100 * deltaTime / _currentHotkeyProvider.HoldDuration, 0, 100); _currentHotkeyDuration.style.width = new StyleLength(Length.Percent(width)); if (!(width >= 100)) return; if (!_currentHotkeyProvider.Enabled) return; _currentHotkeyProvider.OnPerform(); UXService.Return(); } } protected override void OnPanelEntry() { base.OnPanelEntry(); infoLabel.text = "选择快速动作"; var count = _hotkeyCollection.Hotkeys.Count(); if (count is 0) { infoLabel.text = "目前没有快速动作"; } for (var i = 0; i < count; i++) { var hotkey = _hotkeyCollection.Hotkeys.ElementAt(i); var angle = 360 / count * i; var pos = Quaternion.Euler(0, 0, angle) * Vector3.up * 384; pos.y *= 0.64f; var container =new UXContainer( _container.Create(template.CloneTree)) { button = { text = hotkey.Name, //label.style.backgroundColor = Color.red; focusable = false, clickable =hotkey.HoldDuration is 0 ? new Clickable(OnClick):null }, visualElement = { style = { position = Position.Absolute, }, transform = { position = pos, } } }; container.visualElement.SetEnabled(hotkey.Enabled); container.visualElement.RegisterCallback(OnMouseOver); if (hotkey.HoldDuration > 0) { container.visualElement.RegisterCallback(OnMouseUp); container.visualElement.RegisterCallback(OnMouseDown); } continue; void OnClick() { if (hotkey.Enabled) hotkey.OnPerform(); UXService.Return(); } void OnMouseDown(MouseDownEvent evt) { _currentHotkeyProvider = hotkey; _currentHotkeyDuration = container.visualElement.Q(UXConstant.ProcessBarFill); } void OnMouseUp(MouseUpEvent evt) { if (_currentHotkeyDuration is not null) { _currentHotkeyDuration.style.width = new StyleLength(Length.Percent(0)); } _currentHotkeyProvider = null; } void OnMouseOver(MouseOverEvent evt) { infoLabel.text = hotkey.Description; } } inputActionGroup.RegisterCallback(escapeAction, OnEscape); inputActionGroup.RegisterCallback(radialMenuAction, OnRadialMenu); inputActionGroup.RegisterCallback(cancelAction, OnEscape); } private void OnRadialMenu(InputAction.CallbackContext obj) { //if (playerService.LocalPlayer is null) return; switch (obj) { case {interaction:HoldInteraction,canceled:true}: UXService.Entry(); break; } } protected override void OnPanelExit() { base.OnPanelExit(); _currentHotkeyProvider = null; _currentHotkeyDuration = null; _container.Clear(); inputActionGroup.UnRegisterCallback(escapeAction, OnEscape); inputActionGroup.UnRegisterCallback(radialMenuAction, OnRadialMenu); inputActionGroup.UnRegisterCallback(cancelAction, OnEscape); } } }