using AppUI.Manager.Role;
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace AppUI.Util.Avatar
{
[Serializable]
public struct AvatarItem
{
public int id;
public Sprite avatar;
public string name;
public Transform avatarLine;
}
///
/// 预设头像网格:点击项更新 ,并可通过 与 等串联。
///
public class AvatarGroup : MonoBehaviour
{
[SerializeField]
Sprite[] _avatars;
[Tooltip("可选:与 _avatars 一一对应的服务端 avatarID;未配置或长度不一致时用 RoleManager.PresetGridIndexToAvatarId")]
[SerializeField]
int[] _presetAvatarIds;
/// 与 Inspector 中配置的头像 Sprite 数组同源,供 等读取,避免重复配置。
public Sprite[] Avatars => _avatars;
/// 头像数量,与 长度一致。
public int AvatarCount => _avatars != null ? _avatars.Length : 0;
List _avatarItems;
public GameObject imagePanel;
public GameObject imageObj;
/// 选中后写入的 Image; 可在运行时赋值为 avatarPreviewImage 以共用同一预览图。
public Image targetImage;
[Header("关联输入框文案颜色(可选)")]
[SerializeField]
TMP_InputField linkedInputField;
[SerializeField]
TMP_Text linkedLabelText;
[SerializeField]
Color textColorWhenHasValue = Color.black;
[SerializeField]
Color textColorWhenEmpty = new Color(0.5f, 0.5f, 0.5f, 1f);
[Header("关联输入框图标(可选,与上面同一套 hasValue 逻辑)")]
[SerializeField]
Image linkedStateImage;
[SerializeField]
Sprite spriteWhenHasValue;
[SerializeField]
Sprite spriteWhenEmpty;
/// 当前选中下标,与 一致。
public int SelectedIndex { get; private set; }
/// 用户点击或通过 选中时触发(含索引与 Sprite)。
public event Action OnAvatarSelected;
void OnEnable()
{
BindLinkedInputField();
}
void OnDisable()
{
UnbindLinkedInputField();
}
void Start()
{
BuildListIfNeeded();
if (_avatarItems != null && _avatarItems.Count > 0 && _avatars != null && _avatars.Length > 0)
SelectByIndex(0, notify: false);
RefreshLinkedLabelTextColor();
}
void BindLinkedInputField()
{
if (linkedInputField == null)
return;
linkedInputField.onValueChanged.RemoveListener(OnLinkedInputValueChanged);
linkedInputField.onValueChanged.AddListener(OnLinkedInputValueChanged);
RefreshLinkedLabelTextColor();
}
void UnbindLinkedInputField()
{
if (linkedInputField == null)
return;
linkedInputField.onValueChanged.RemoveListener(OnLinkedInputValueChanged);
}
void OnLinkedInputValueChanged(string _)
{
RefreshLinkedLabelTextColor();
}
///
/// 根据 是否有内容:更新 颜色、
/// 的 Sprite(有值 / 空 两套)。
///
public void RefreshLinkedLabelTextColor()
{
var hasValue = linkedInputField != null && linkedInputField.text.Trim().Length > 0;
if (linkedLabelText != null)
linkedLabelText.color = hasValue ? textColorWhenHasValue : textColorWhenEmpty;
if (linkedStateImage == null)
return;
var sp = hasValue ? spriteWhenHasValue : spriteWhenEmpty;
if (sp != null)
linkedStateImage.sprite = sp;
}
void BuildListIfNeeded()
{
if (_avatarItems != null)
return;
_avatarItems = new List();
if (_avatars == null || _avatars.Length == 0 || imagePanel == null || imageObj == null)
return;
for (var i = 0; i < _avatars.Length; i++)
{
var item = new AvatarItem
{
id = i,
avatar = _avatars[i],
name = $"Avatar {i}"
};
var o = Instantiate(imageObj, imagePanel.transform);
var img = o.GetComponent();
if (img != null)
img.sprite = item.avatar;
var lineTr = o.transform.Find("AvatarLine");
if (lineTr != null)
item.avatarLine = lineTr;
_avatarItems.Add(item);
o.SetActive(true);
var index = i;
var btn = o.GetComponent