using System.Collections.Generic; using FairyGUI; using UnityEngine; namespace NBF { public class ButtonNavigate { private readonly List _buttons = new List(); private int _currentIndex = 0; public ButtonNavigate(List buttons, bool selectFist = true) { _buttons.AddRange(buttons); if (selectFist && _buttons.Count > 0) { SetButtonSelect(buttons[0]); } } public void Up() { Navigate(Vector2.up); } public void Down() { Navigate(Vector2.down); } public void Left() { Navigate(Vector2.left); } public void Right() { Navigate(Vector2.right); } /// /// 点击选中按钮 /// public void Click() { foreach (var button in _buttons) { if (button.selected) { button.Click(); break; } } } private void Navigate(Vector2 direction) { GButton current = _buttons[_currentIndex]; Rect currentRect = GetGlobalRect(current); GButton bestCandidate = null; float bestDistance = float.MaxValue; foreach (var candidate in _buttons) { if (candidate == current) continue; Rect candidateRect = GetGlobalRect(candidate); // 检查方向匹配性 bool isDirectionMatch = false; if (direction == Vector2.up) // 上方向 { isDirectionMatch = candidateRect.yMax <= currentRect.yMin && RectOverlapX(currentRect, candidateRect); } else if (direction == Vector2.down) // 下方向 { isDirectionMatch = candidateRect.yMin >= currentRect.yMax && RectOverlapX(currentRect, candidateRect); } else if (direction == Vector2.left) // 左方向 { isDirectionMatch = candidateRect.xMax <= currentRect.xMin && RectOverlapY(currentRect, candidateRect); } else if (direction == Vector2.right) // 右方向 { isDirectionMatch = candidateRect.xMin >= currentRect.xMax && RectOverlapY(currentRect, candidateRect); } if (isDirectionMatch) { float distance = Vector2.Distance(currentRect.center, candidateRect.center); if (distance < bestDistance) { bestDistance = distance; bestCandidate = candidate; } } } if (bestCandidate != null) { _currentIndex = _buttons.IndexOf(bestCandidate); SetButtonSelect(bestCandidate); } } /// /// 获取按钮在根坐标空间中的矩形区域 /// /// /// private Rect GetGlobalRect(GObject obj) { // 获取对象在根组件中的全局位置 Vector2 globalPos = obj.LocalToGlobal(Vector2.zero); Vector2 rootPos = GRoot.inst.GlobalToLocal(globalPos); // 考虑对象的缩放 float width = obj.width * obj.scaleX; float height = obj.height * obj.scaleY; return new Rect(rootPos.x, rootPos.y, width, height); } /// /// 检查两个矩形在X轴上的重叠 /// /// /// /// private bool RectOverlapX(Rect a, Rect b) { return !(a.xMin >= b.xMax || a.xMax <= b.xMin); } /// /// 检查两个矩形在Y轴上的重叠 /// /// /// /// private bool RectOverlapY(Rect a, Rect b) { return !(a.yMin >= b.yMax || a.yMax <= b.yMin); } /// /// 设置按钮选中 /// /// private void SetButtonSelect(GButton button) { foreach (var btn in _buttons) { btn.selected = btn == button; } } } }