feat(ui): 添加 Terminal 风格主界面 UI 系统
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
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<ChapterVo> _chapters = new List<ChapterVo>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user