HKMBFZ/Assets/Scripts/Szz_Scripts/UI/CustomUI/FocusManager.cs

226 lines
9.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ---------------- FocusManager ----------------
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
public class FocusManager : MonoBehaviour
{
public static FocusManager Instance { get; private set; }
[Header("导航按钮")]
public Button nextFocusButton;
public Button previousFocusButton;
public Button firstFocusButton;
public Button lastFocusButton;
[Header("下拉菜单控制按钮")]
public Button dropdownToggleButton;
public Button dropdownNextButton;
public Button dropdownPreviousButton;
public Button dropdownSubmitButton;
[Header("状态显示")]
public TextMeshProUGUI dropdownStatusText;
public TextMeshProUGUI pageStatusText;
public TextMeshProUGUI inputStatusText;
[Header("调试")]
public TextMeshProUGUI debugText;
public FocusPage currentPage;
private bool isProcessingInput = false;
void Awake()
{
if (Instance == null) { Instance = this;}
//else { Destroy(gameObject); return; }
SetupButtonListeners();
}
void Update()
{
HandleKeyboardNavigation();
UpdateStatusDisplay();
UpdateDebugInfo();
}
public void ForceUpdateButtonStates() => UpdateButtonStates();
public void SetCurrentPage(FocusPage page)
{
if (page == null) return;
currentPage?.ClearFocus();
currentPage = page;
ForceUpdateButtonStates();
UpdateStatusDisplay();
}
public FocusPage GetCurrentPage() => currentPage;
#region
public void FocusNext() { if (currentPage == null || isProcessingInput || currentPage.focusDisabled) return; StartCoroutine(ProcessInputCoroutine(() => currentPage.FocusNext())); }
public void FocusPrevious() { if (currentPage == null || isProcessingInput || currentPage.focusDisabled) return; StartCoroutine(ProcessInputCoroutine(() => currentPage.FocusPrevious())); }
public void FocusFirst() { if (currentPage == null || isProcessingInput || currentPage.focusDisabled) return; StartCoroutine(ProcessInputCoroutine(() => currentPage.FocusFirst())); }
public void FocusLast() { if (currentPage == null || isProcessingInput|| currentPage.focusDisabled) return; StartCoroutine(ProcessInputCoroutine(() => currentPage.FocusLast())); }
public void DropdownSelectNext() { if (currentPage == null || isProcessingInput || currentPage.focusDisabled) return; StartCoroutine(ProcessInputCoroutine(() => currentPage.DropdownSelectNext())); }
public void DropdownSelectPrevious() { if (currentPage == null || isProcessingInput || currentPage.focusDisabled) return; StartCoroutine(ProcessInputCoroutine(() => currentPage.DropdownSelectPrevious())); }
public void DropdownSubmit() { if (currentPage == null || isProcessingInput || currentPage.focusDisabled) return; StartCoroutine(ProcessInputCoroutine(() => currentPage.DropdownSubmit())); }
public void DropdownToggle() { if (currentPage == null || isProcessingInput || currentPage.focusDisabled) return; StartCoroutine(ProcessInputCoroutine(() => currentPage.DropdownToggle())); }
private IEnumerator ProcessInputCoroutine(System.Action action)
{
if (isProcessingInput) yield break;
isProcessingInput = true;
action?.Invoke();
// 不要等到 EndOfFrame
yield return null;
isProcessingInput = false;
UpdateButtonStates();
}
#endregion
#region
private void SetupButtonListeners()
{
if (nextFocusButton != null) nextFocusButton.onClick.AddListener(FocusNext);
if (previousFocusButton != null) previousFocusButton.onClick.AddListener(FocusPrevious);
if (firstFocusButton != null) firstFocusButton.onClick.AddListener(FocusFirst);
if (lastFocusButton != null) lastFocusButton.onClick.AddListener(FocusLast);
if (dropdownToggleButton != null) dropdownToggleButton.onClick.AddListener(DropdownToggle);
if (dropdownNextButton != null) dropdownNextButton.onClick.AddListener(DropdownSelectNext);
if (dropdownPreviousButton != null) dropdownPreviousButton.onClick.AddListener(DropdownSelectPrevious);
if (dropdownSubmitButton != null) dropdownSubmitButton.onClick.AddListener(DropdownSubmit);
}
// 这里省略其他未改动部分,主要修改按钮状态逻辑
private void UpdateButtonStates()
{
if (currentPage == null)
{
SetAllButtonsInteractable(false);
return;
}
bool isDropdownExpanded = currentPage.IsDropdownExpanded();
bool isOnDropdown = currentPage.IsOnDropdown();
bool hasInputFocus = currentPage.HasActiveInputField();
if (previousFocusButton != null)
previousFocusButton.interactable = currentPage.HasPreviousFocus && !isDropdownExpanded && !hasInputFocus && !isProcessingInput;
if (nextFocusButton != null)
nextFocusButton.interactable = currentPage.HasNextFocus && !isDropdownExpanded && !hasInputFocus && !isProcessingInput;
bool hasElements = currentPage.FocusCount > 0 && !isDropdownExpanded && !hasInputFocus && !isProcessingInput;
if (firstFocusButton != null) firstFocusButton.interactable = hasElements;
if (lastFocusButton != null) lastFocusButton.interactable = hasElements;
// Submit可用条件
if (dropdownToggleButton != null) dropdownToggleButton.interactable = isOnDropdown && !hasInputFocus && !isProcessingInput;
if (dropdownNextButton != null) dropdownNextButton.interactable = isDropdownExpanded && !hasInputFocus && !isProcessingInput;
if (dropdownPreviousButton != null) dropdownPreviousButton.interactable = isDropdownExpanded && !hasInputFocus && !isProcessingInput;
if (dropdownSubmitButton != null) dropdownSubmitButton.interactable = (isDropdownExpanded || isOnDropdown) && !hasInputFocus && !isProcessingInput;
}
private void SetAllButtonsInteractable(bool interactable)
{
if (previousFocusButton != null) previousFocusButton.interactable = interactable;
if (nextFocusButton != null) nextFocusButton.interactable = interactable;
if (firstFocusButton != null) firstFocusButton.interactable = interactable;
if (lastFocusButton != null) lastFocusButton.interactable = interactable;
if (dropdownToggleButton != null) dropdownToggleButton.interactable = interactable;
if (dropdownNextButton != null) dropdownNextButton.interactable = interactable;
if (dropdownPreviousButton != null) dropdownPreviousButton.interactable = interactable;
if (dropdownSubmitButton != null) dropdownSubmitButton.interactable = interactable;
}
#endregion
#region
private void UpdateStatusDisplay()
{
if (currentPage == null)
{
if (dropdownStatusText != null) dropdownStatusText.text = "无活动页面";
if (pageStatusText != null) pageStatusText.text = "";
if (inputStatusText != null) inputStatusText.text = "";
return;
}
if (pageStatusText != null) pageStatusText.text = $"焦点: {currentPage.CurrentFocusIndex + 1}/{currentPage.FocusCount}";
if (inputStatusText != null) inputStatusText.text = currentPage.HasActiveInputField() ? "输入模式" : "";
if (dropdownStatusText != null)
{
if (currentPage.IsDropdownExpanded())
{
dropdownStatusText.text = $"选择中: {currentPage.GetCurrentDropdownValue()}";
}
else if (currentPage.IsOnDropdown())
{
dropdownStatusText.text = "按[提交]开始选择";
}
else dropdownStatusText.text = "";
}
}
private void UpdateDebugInfo()
{
if (debugText != null && currentPage != null)
{
debugText.text = $"处理中: {isProcessingInput}\n" +
$"输入焦点: {currentPage.HasActiveInputField()}\n" +
$"下拉展开: {currentPage.IsDropdownExpanded()}";
}
}
#endregion
#region
private void HandleKeyboardNavigation()
{
if (currentPage == null) return;
bool hasInputFocus = currentPage.HasActiveInputField();
if (hasInputFocus)
{
if (Input.GetKeyDown(KeyCode.Escape))
StartCoroutine(ProcessInputCoroutine(() => currentPage.DeactivateCurrentInputField()));
return;
}
// Dropdown键盘操作直接调用
if (currentPage.IsOnDropdown())
{
if (Input.GetKeyDown(KeyCode.UpArrow)) currentPage.DropdownSelectPrevious();
if (Input.GetKeyDown(KeyCode.DownArrow)) currentPage.DropdownSelectNext();
//if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
// currentPage.DropdownSubmit(); // 内部判断是打开还是提交
//if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.Escape))
// currentPage.DropdownToggle();
}
else
{
//// 普通焦点切换用协程限制重复输入
//if (Input.GetKeyDown(KeyCode.Tab))
//{
// if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
// SafeFocusPrevious();
// else
// SafeFocusNext();
//}
if (Input.GetKeyDown(KeyCode.Home)) FocusFirst();
if (Input.GetKeyDown(KeyCode.End)) FocusLast();
}
}
#endregion
}