using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; namespace AibisDream.UI.Terminal { public class TerminalChapterPanel : MonoBehaviour, IUIPanel { [SerializeField] private TerminalPanelAnimator panelAnimator; [SerializeField] private TerminalHeaderView header; [SerializeField] private TerminalChapterItemView leftPreview; [SerializeField] private TerminalChapterItemView currentView; [SerializeField] private TerminalChapterItemView rightPreview; [SerializeField] private TMP_Text emptyText; [SerializeField] private TMP_Text selectedTitleText; [SerializeField] private Button previousButton; [SerializeField] private Button nextButton; [SerializeField] private Button continueButton; [SerializeField] private Button restartButton; [SerializeField] private Button backButton; private readonly List _chapters = new List(); private int _currentIndex; public bool IsOpen => gameObject.activeSelf; public bool IsCloseable => true; private void Awake() { previousButton?.onClick.AddListener(Previous); nextButton?.onClick.AddListener(Next); continueButton?.onClick.AddListener(Continue); restartButton?.onClick.AddListener(Restart); backButton?.onClick.AddListener(Close); } private void OnDestroy() { previousButton?.onClick.RemoveListener(Previous); nextButton?.onClick.RemoveListener(Next); continueButton?.onClick.RemoveListener(Continue); restartButton?.onClick.RemoveListener(Restart); backButton?.onClick.RemoveListener(Close); } public void Show() { header?.SetText("<选择章节>", string.Empty); LoadChapters(); RefreshViews(); if (panelAnimator != null) { panelAnimator.Show(); } else { gameObject.SetActive(true); } } public void Hide() { if (panelAnimator != null) { panelAnimator.Hide(); } else { gameObject.SetActive(false); } } public void Close() { UIManager.Instance.HidePreferredChapterPanel(); } private void LoadChapters() { _chapters.Clear(); var chapters = ChapterController.Instance.GetChapterList(); _chapters.AddRange(chapters); _currentIndex = Mathf.Clamp(_currentIndex, 0, Mathf.Max(0, _chapters.Count - 1)); } private void RefreshViews() { var hasChapters = _chapters.Count > 0; if (emptyText != null) { emptyText.gameObject.SetActive(!hasChapters); } SetViewActive(leftPreview, hasChapters && _chapters.Count > 1); SetViewActive(currentView, hasChapters); SetViewActive(rightPreview, hasChapters && _chapters.Count > 1); if (!hasChapters) { if (selectedTitleText != null) { selectedTitleText.text = "NO CHAPTER DATA"; } continueButton?.gameObject.SetActive(false); restartButton?.gameObject.SetActive(false); return; } var current = _chapters[_currentIndex]; currentView?.Init(current, selected: true, preview: false); leftPreview?.Init(_chapters[LoopIndex(_currentIndex - 1)], selected: false, preview: true); rightPreview?.Init(_chapters[LoopIndex(_currentIndex + 1)], selected: false, preview: true); if (selectedTitleText != null) { selectedTitleText.text = current.title; } continueButton?.gameObject.SetActive(current.hasSaveFile); restartButton?.gameObject.SetActive(true); } private static void SetViewActive(TerminalChapterItemView view, bool active) { if (view != null) { view.gameObject.SetActive(active); } } private int LoopIndex(int index) { if (_chapters.Count == 0) { return 0; } return (index + _chapters.Count) % _chapters.Count; } private void Previous() { if (_chapters.Count == 0) { return; } _currentIndex = LoopIndex(_currentIndex - 1); RefreshViews(); } private void Next() { if (_chapters.Count == 0) { return; } _currentIndex = LoopIndex(_currentIndex + 1); RefreshViews(); } private void Continue() { if (_chapters.Count == 0 || !_chapters[_currentIndex].hasSaveFile) { return; } ChapterController.Instance.StartWithSaveFile(); Close(); } private void Restart() { if (_chapters.Count == 0) { return; } ChapterController.Instance.StartWithChapter(_chapters[_currentIndex]); Close(); } } }