using System; using System.Collections.Generic; using UnityEngine; namespace AibisDream.UI { public enum InGameTerminalPage { None, Setting, Record, } /// /// 局内终端 Panel 壳:管理 Setting / Record 两个 Page。 /// Setting / Record 需在场景中分别挂独立的 Prefab 实例,并在 Inspector 中绑定。 /// public class InGameTerminalPanel : MonoBehaviour, IUIPanel, ITerminalPanelHost { [SerializeField] private TerminalHeaderView header; [SerializeField] private TerminalSettingPanel settingPage; [SerializeField] private TerminalRecordPanel recordPage; private readonly Stack _backStack = new(); private InGameTerminalPage _currentPage = InGameTerminalPage.None; private bool _pausedByPanel; private bool _isReturningToMainMenu; public bool IsOpen => gameObject.activeSelf && _currentPage != InGameTerminalPage.None; public bool IsCloseable => false; public InGameTerminalPage CurrentPage => _currentPage; public bool IsInGameContext => true; public void Initialize() { var root = transform; settingPage ??= root.GetComponentInChildren(true); recordPage ??= root.GetComponentInChildren(true); settingPage?.SetOwner(this); recordPage?.SetOwner(this); if (!HasRequiredPages()) { Debug.LogError("[InGameTerminalPanel] Missing required pages. Assign TerminalSettingPanel and TerminalRecordPanel on the in-game shell."); } Close(); } public bool HasRequiredPages() { return settingPage != null && recordPage != null; } public void Show() { Open(InGameTerminalPage.Setting); } public void Hide() { Close(); } public void Open(InGameTerminalPage page) { if (!HasRequiredPages() || page == InGameTerminalPage.None) { return; } _isReturningToMainMenu = false; if (!IsOpen) { _backStack.Clear(); } gameObject.SetActive(true); PauseIfNeeded(); SwitchTo(page, pushCurrent: false); } public void SwitchTo(InGameTerminalPage page, bool pushCurrent = true) { if (page == InGameTerminalPage.None || page == _currentPage) { return; } if (pushCurrent && _currentPage != InGameTerminalPage.None) { _backStack.Push(_currentPage); } var previous = _currentPage; _currentPage = page; if (previous == InGameTerminalPage.None) { ShowPage(_currentPage); return; } HidePage(previous, () => ShowPage(_currentPage)); } public void Back() { if (_backStack.Count > 0) { var previous = _backStack.Pop(); var current = _currentPage; _currentPage = previous; HidePage(current, () => ShowPage(_currentPage)); return; } Close(); } public bool HandleEscape() { if (!IsOpen) { return false; } if (_isReturningToMainMenu) { return true; } Back(); return true; } public void Close() { if (_isReturningToMainMenu) { return; } Close(restoreAmb: true); } public void Close(bool restoreAmb) { HideAllPages(); _backStack.Clear(); _currentPage = InGameTerminalPage.None; ContinueIfPaused(restoreAmb); gameObject.SetActive(false); } public void CloseToMainMenu() { if (_isReturningToMainMenu || GameManager.Instance == null) { return; } if (GameManager.Instance.TryReturnToMainMenu()) { // Keep this full-screen panel visible while the global transition // covers the gameplay behind it. GameManager closes it only after // the screen is fully covered. _isReturningToMainMenu = true; } } public void CloseForSessionEnd() { HideAllPages(); _backStack.Clear(); _currentPage = InGameTerminalPage.None; if (_pausedByPanel) { TerminalUIAudio.NotifyPauseMenuAmbExit(restorePrevious: false); _pausedByPanel = false; } _isReturningToMainMenu = false; gameObject.SetActive(false); } public void SetHeader(string title, string status = "") { header?.SetText(title, status); } public void AppendDialogLine(LineInfo lineInfo) { recordPage?.AppendDialogLine(lineInfo); } public void ClearDialog() { recordPage?.ClearDialog(); } private void PauseIfNeeded() { if (GameManager.Instance == null || !GameManager.Session.CanPause || _pausedByPanel) { return; } GameManager.Instance.TryPause(); TerminalUIAudio.NotifyPauseMenuAmbEnter(); _pausedByPanel = true; } private void ContinueIfPaused(bool restoreAmb = true) { if (!_pausedByPanel) { return; } GameManager.Instance.TryResume(); TerminalUIAudio.NotifyPauseMenuAmbExit(restoreAmb); _pausedByPanel = false; } private void ShowPage(InGameTerminalPage page) { switch (page) { case InGameTerminalPage.Setting: settingPage?.Show(); break; case InGameTerminalPage.Record: recordPage?.Show(); break; } } private void HidePage(InGameTerminalPage page, Action onComplete = null) { switch (page) { case InGameTerminalPage.Setting: settingPage?.Hide(onComplete); break; case InGameTerminalPage.Record: recordPage?.Hide(onComplete); break; default: onComplete?.Invoke(); break; } } private void HideAllPages() { settingPage?.Hide(); recordPage?.Hide(); } } }