264 lines
7.0 KiB
C#
264 lines
7.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace AibisDream.UI
|
|
{
|
|
public enum InGameTerminalPage
|
|
{
|
|
None,
|
|
Setting,
|
|
Record,
|
|
}
|
|
|
|
/// <summary>
|
|
/// 局内终端 Panel 壳:管理 Setting / Record 两个 Page。
|
|
/// Setting / Record 需在场景中分别挂独立的 Prefab 实例,并在 Inspector 中绑定。
|
|
/// </summary>
|
|
public class InGameTerminalPanel : MonoBehaviour, IUIPanel, ITerminalPanelHost
|
|
{
|
|
[SerializeField] private TerminalHeaderView header;
|
|
[SerializeField] private TerminalSettingPanel settingPage;
|
|
[SerializeField] private TerminalRecordPanel recordPage;
|
|
|
|
private readonly Stack<InGameTerminalPage> _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<TerminalSettingPanel>(true);
|
|
recordPage ??= root.GetComponentInChildren<TerminalRecordPanel>(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();
|
|
}
|
|
}
|
|
}
|