using System; using AibisDream.Utility; using TMPro; using UnityEngine; using UnityEngine.Localization.Components; using UnityEngine.UI; namespace AibisDream.UI { [RequireComponent(typeof(BaseButton))] public class TerminalMenuItemView : MonoBehaviour { [SerializeField] private TMP_Text labelText; [SerializeField] private LocalizeStringEvent labelLocalize; [SerializeField] private TMP_Text statusText; [SerializeField] private TMP_Text detailText; [SerializeField] private TMP_Text cursor; [SerializeField] private Image selectionBar; [SerializeField] private string defaultLabelKey = string.Empty; [SerializeField] private Color normalTextColor = Color.white; [SerializeField] private Color selectedTextColor = new Color(0.02f, 0.02f, 0.04f); [SerializeField] private Color dangerTextColor = new Color(1f, 0.18f, 0.2f); [SerializeField] private float disabledAlpha = 0.35f; private BaseButton _button; private CanvasGroup _canvasGroup; private bool _isDanger; private bool _isSelected; private SelectionType _prevSelectionState = SelectionType.Normal; public event Action Clicked; public event Action Hovered; private void Awake() { _button = GetComponent(); _canvasGroup = GetComponent(); if (_canvasGroup == null) { _canvasGroup = gameObject.AddComponent(); } if (labelLocalize == null && labelText != null) { labelLocalize = labelText.GetComponent(); } _button.onClick.AddListener(HandleClick); _button.onStateTransition.AddListener(OnButtonStateTransition); SetSelected(false); if (!string.IsNullOrEmpty(defaultLabelKey)) { SetLabel(defaultLabelKey); } } private void OnDestroy() { if (_button != null) { _button.onClick.RemoveListener(HandleClick); _button.onStateTransition.RemoveListener(OnButtonStateTransition); } } public void SetContent(string label, string status = "", string detail = "") { SetLabel(label); if (statusText != null) { statusText.text = status; } if (detailText != null) { detailText.text = detail; } RefreshVisual(); } public void SetLabel(string value) { if (labelLocalize != null && IsLocalizationKey(value)) { labelLocalize.enabled = true; labelLocalize.SetTable(ConstRef.UITextTable); labelLocalize.SetEntry(value); return; } if (labelLocalize != null) { labelLocalize.enabled = false; } if (labelText != null) { labelText.text = value; } } public void SetInteractable(bool interactable) { if (_button != null) { _button.interactable = interactable; } if (_canvasGroup != null) { _canvasGroup.alpha = interactable ? 1f : disabledAlpha; } } public void SetSelected(bool selected) { _isSelected = selected; RefreshVisual(); } private void HandleClick() { if (_button != null && _button.interactable) { TerminalUIAudio.NotifyClick(); } Clicked?.Invoke(this); } private void OnButtonStateTransition(SelectionType state, bool instant) { if (_button.interactable && state == SelectionType.Highlighted && _prevSelectionState == SelectionType.Normal) { TerminalUIAudio.NotifyHover(); } _prevSelectionState = state; if (state is SelectionType.Highlighted or SelectionType.Selected or SelectionType.Pressed) { Hovered?.Invoke(this); } RefreshVisual(); } private void RefreshVisual() { if (cursor != null) { cursor.gameObject.SetActive(_isSelected); } if (selectionBar != null) { selectionBar.gameObject.SetActive(_isSelected); } var color = _isDanger ? dangerTextColor : normalTextColor; if (_isSelected && !_isDanger) { color = selectedTextColor; } SetColor(labelText, color); SetColor(statusText, color); SetColor(detailText, color); SetColor(cursor, color); } private static void SetColor(TMP_Text text, Color color) { if (text != null) { text.color = color; } } private static bool IsLocalizationKey(string value) { return !string.IsNullOrEmpty(value) && value.Contains("_", StringComparison.Ordinal); } } }