Files
aibis-dream/Assets/Scripts/UI/Form/SelectItem.cs
T
dingyuntian e015b756f6 feat(audio-kit): 终端 UI 菜单音效与暂停菜单环境音
- 新增 TerminalUIAudio 事件通知与 TerminalUIAudioBehaviour 组件
- TerminalButton/TerminalMenuItemView/SelectItem/SliderItem 接入悬停与点击音效
- AudioManager 监听 TerminalUIEvent 播放 menu_hover/menu_click
- 新增 PauseMenu 环境音状态及恢复逻辑
- 新增 MainMenuStage FMOD 参数控制
- BaseButton 调用基类 DoStateTransition 保证状态事件正确触发
- 为 TerminalChapterPanel Prefab 添加 TerminalUIAudioBehaviour
2026-07-04 23:12:47 +08:00

220 lines
6.6 KiB
C#

using System;
using AibisDream.UI;
using AibisDream.Utility;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Localization.Components;
using UnityEngine.UI;
namespace AibisDream
{
public class SelectItem : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[SerializeField] private TMP_Text labelText;
[SerializeField] private LocalizeStringEvent labelLocalize;
[SerializeField] private TMP_Text showText;
[SerializeField] private LocalizeStringEvent showLocalize;
[SerializeField] private Button leftBtn;
[SerializeField] private Button rightBtn;
[SerializeField] private Image selectionBar;
[SerializeField] private float selectionBarHiddenAlpha;
[SerializeField] private float selectionBarVisibleAlpha = 1f;
[SerializeField] private Color normalTextColor = Color.white;
[SerializeField] private Color hoveredTextColor = new Color(0.02f, 0.02f, 0.04f);
[SerializeField] private ColorBlock lightRowButtonColors = new ColorBlock
{
normalColor = new Color(0.02f, 0.02f, 0.04f, 1f),
highlightedColor = new Color(0.35f, 0.35f, 0.4f, 1f),
pressedColor = new Color(0.55f, 0.55f, 0.6f, 1f),
selectedColor = new Color(0.02f, 0.02f, 0.04f, 1f),
disabledColor = new Color(0.78431374f, 0.78431374f, 0.78431374f, 0.5019608f),
colorMultiplier = 1f,
fadeDuration = 0.1f
};
private string _propName;
private UIFormOption[] _options = Array.Empty<UIFormOption>();
private int _curIdx;
private Action<string, string> _onValueChanged;
private bool _isListening;
private bool _isHovered;
private ColorBlock _darkRowButtonColors;
private void Awake()
{
if (leftBtn != null)
{
_darkRowButtonColors = leftBtn.colors;
}
SetHovered(false);
if (!_isListening)
{
leftBtn?.onClick.AddListener(LeftRoll);
rightBtn?.onClick.AddListener(RightRoll);
_isListening = leftBtn != null || rightBtn != null;
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (!_isHovered)
{
_isHovered = true;
TerminalUIAudio.NotifyHover();
}
SetHovered(true);
}
public void OnPointerExit(PointerEventData eventData)
{
_isHovered = false;
SetHovered(false);
}
private void SetHovered(bool hovered)
{
SetSelectionBarAlpha(hovered ? selectionBarVisibleAlpha : selectionBarHiddenAlpha);
var textColor = hovered ? hoveredTextColor : normalTextColor;
SetTextColor(labelText, textColor);
SetTextColor(showText, textColor);
var buttonColors = hovered ? lightRowButtonColors : _darkRowButtonColors;
ApplyButtonColors(leftBtn, buttonColors);
ApplyButtonColors(rightBtn, buttonColors);
}
private static void SetTextColor(TMP_Text text, Color color)
{
if (text != null)
{
text.color = color;
}
}
private static void ApplyButtonColors(Button button, ColorBlock colors)
{
if (button != null)
{
button.colors = colors;
}
}
private void SetSelectionBarAlpha(float alpha)
{
if (selectionBar == null)
{
return;
}
var color = selectionBar.color;
color.a = alpha;
selectionBar.color = color;
}
private void OnDestroy()
{
if (!_isListening)
{
return;
}
leftBtn?.onClick.RemoveListener(LeftRoll);
rightBtn?.onClick.RemoveListener(RightRoll);
_isListening = false;
}
public void Init(string propName, string label, UIFormOption[] options, Action<string, string> onValueChanged)
{
_propName = propName;
_options = options ?? Array.Empty<UIFormOption>();
_onValueChanged = onValueChanged;
if (leftBtn == null || rightBtn == null)
{
Debug.LogError($"[SelectItem] Buttons not assigned on {name}.", this);
}
SetDisplayText(labelText, labelLocalize, label);
RefreshValue();
}
public void SetValue(string value)
{
var idx = Array.FindIndex(_options, item => item.prop == value);
if (idx < 0)
{
Debug.LogWarning($"[SelectItem] {_propName} value '{value}' not found on {name}; fallback to first option.");
idx = 0;
}
_curIdx = Mathf.Clamp(idx, 0, Mathf.Max(0, _options.Length - 1));
RefreshValue();
}
private void LeftRoll()
{
Step(1);
}
private void RightRoll()
{
Step(-1);
}
private void Step(int offset)
{
if (_options.Length == 0)
{
return;
}
_curIdx = CommonUtil.LoopStep(_curIdx, 0, _options.Length - 1, offset);
RefreshValue();
_onValueChanged?.Invoke(_propName, _options[_curIdx].prop);
TerminalUIAudio.NotifyClick();
}
private void RefreshValue()
{
if (_options.Length == 0)
{
SetDisplayText(showText, showLocalize, string.Empty);
return;
}
SetDisplayText(showText, showLocalize, _options[_curIdx].label);
}
private static void SetDisplayText(TMP_Text text, LocalizeStringEvent localize, string value)
{
if (localize != null && IsLocalizationKey(value))
{
localize.enabled = true;
localize.SetTable(ConstRef.UITextTable);
localize.SetEntry(value);
return;
}
if (localize != null)
{
localize.enabled = false;
}
if (text != null)
{
text.text = value;
}
}
private static bool IsLocalizationKey(string value)
{
return !string.IsNullOrEmpty(value) && value.StartsWith("setting_", StringComparison.Ordinal);
}
}
}