首次提交

This commit is contained in:
Bob.Song
2026-03-05 18:07:55 +08:00
commit e125bb869e
4534 changed files with 563920 additions and 0 deletions

View File

@@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using FairyGUI;
using UnityEngine;
namespace NBF
{
public class ListSelector
{
private GList _list;
private readonly List<Type> _ignores = new List<Type>();
// private readonly List<GObject> _items = new List<GObject>();
private float itemWidth = 200f;
private float itemHeight = 180f;
public object SelectedItem => _list.selectedIndex > 0 ? _list.GetChildAt(_list.selectedIndex) : null;
public ListSelector(GList list, params Type[] ignores)
{
_list = list;
if (ignores != null && ignores.Length > 0)
{
_ignores.AddRange(ignores);
}
}
#region
public void Refresh()
{
var children = _list.GetChildren();
foreach (var item in children)
{
if (_ignores.Contains(item.GetType())) continue;
itemWidth = item.width;
itemHeight = item.height;
break;
}
}
#endregion
#region
public void Up()
{
Move(Vector2.up);
}
public void Down()
{
Move(Vector2.down);
}
public void Right()
{
Move(Vector2.right);
}
public void Left()
{
Move(Vector2.left);
}
public void Move(Vector2 direction)
{
if (_list.selectedIndex == -1)
{
// 首次选择第一个可选中项
SelectFirstSelectable();
return;
}
var currentPos = GetItemPosition(_list.selectedIndex);
var nearestIndex = FindNearestSelectableItem(currentPos, direction);
// 如果是左右移动且未找到目标,则尝试寻找前一个或后一个可选项
if (nearestIndex == -1 && (direction == Vector2.left || direction == Vector2.right))
{
if (direction == Vector2.left)
{
// 寻找前一个可选项
nearestIndex = FindPreviousSelectableItem(_list.selectedIndex);
}
else if (direction == Vector2.right)
{
// 寻找后一个可选项
nearestIndex = FindNextSelectableItem(_list.selectedIndex);
}
}
if (nearestIndex != -1)
{
SetSelection(nearestIndex);
}
}
#endregion
#region
private Vector2 GetItemPosition(int index)
{
var item = _list.GetChildAt(index);
return item.position;
}
private int FindNearestSelectableItem(Vector2 fromPos, Vector2 direction)
{
var bestIndex = -1;
var bestDistance = float.MaxValue;
for (var i = 0; i < _list.numItems; i++)
{
if (!IsSelectableItem(i)) continue;
var targetPos = GetItemPosition(i);
var diff = targetPos - fromPos;
// 检查方向匹配度
if (IsDirectionMatch(direction, diff))
{
var distance = Vector2.Distance(fromPos, targetPos);
if (distance < bestDistance && distance > 0.1f)
{
bestDistance = distance;
bestIndex = i;
}
}
}
return bestIndex;
}
private int FindPreviousSelectableItem(int currentIndex)
{
for (int i = currentIndex - 1; i >= 0; i--)
{
if (IsSelectableItem(i))
return i;
}
return -1;
}
private int FindNextSelectableItem(int currentIndex)
{
for (int i = currentIndex + 1; i < _list.numItems; i++)
{
if (IsSelectableItem(i))
return i;
}
return -1;
}
private bool IsDirectionMatch(Vector2 direction, Vector2 diff)
{
if (direction == Vector2.up)
return diff.y < 0 && Mathf.Abs(diff.x) < itemWidth; // 修正向上应该是Y值更小
if (direction == Vector2.down)
return diff.y > 0 && Mathf.Abs(diff.x) < itemWidth; // 修正向下应该是Y值更大
if (direction == Vector2.left)
return diff.x < 0 && Mathf.Abs(diff.y) < itemHeight;
if (direction == Vector2.right)
return diff.x > 0 && Mathf.Abs(diff.y) < itemHeight;
return false;
}
private bool IsSelectableItem(int index)
{
var item = _list.GetChildAt(index);
var ret = !_ignores.Contains(item.GetType());
if (item.GetType() == typeof(ListTitleItem))
{
}
return ret;
}
private void SelectFirstSelectable()
{
for (var i = 0; i < _list.numItems; i++)
{
if (IsSelectableItem(i))
{
SetSelection(i);
break;
}
}
}
private void SetSelection(int index)
{
_list.selectedIndex = index;
_list.ScrollToView(index, true);
}
#endregion
}
}