164 lines
4.8 KiB
C#
164 lines
4.8 KiB
C#
using System.Collections.Generic;
|
|
using FairyGUI;
|
|
using UnityEngine;
|
|
|
|
namespace NBF
|
|
{
|
|
public class ButtonNavigate
|
|
{
|
|
private readonly List<GButton> _buttons = new List<GButton>();
|
|
private int _currentIndex = 0;
|
|
|
|
public ButtonNavigate(List<GButton> 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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 点击选中按钮
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取按钮在根坐标空间中的矩形区域
|
|
/// </summary>
|
|
/// <param name="obj"></param>
|
|
/// <returns></returns>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查两个矩形在X轴上的重叠
|
|
/// </summary>
|
|
/// <param name="a"></param>
|
|
/// <param name="b"></param>
|
|
/// <returns></returns>
|
|
private bool RectOverlapX(Rect a, Rect b)
|
|
{
|
|
return !(a.xMin >= b.xMax || a.xMax <= b.xMin);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查两个矩形在Y轴上的重叠
|
|
/// </summary>
|
|
/// <param name="a"></param>
|
|
/// <param name="b"></param>
|
|
/// <returns></returns>
|
|
private bool RectOverlapY(Rect a, Rect b)
|
|
{
|
|
return !(a.yMin >= b.yMax || a.yMax <= b.yMin);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置按钮选中
|
|
/// </summary>
|
|
/// <param name="button"></param>
|
|
private void SetButtonSelect(GButton button)
|
|
{
|
|
foreach (var btn in _buttons)
|
|
{
|
|
btn.selected = btn == button;
|
|
}
|
|
}
|
|
}
|
|
} |