157 lines
6.1 KiB
C#
157 lines
6.1 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using AK.Wwise;
|
||
using Ichni.Menu;
|
||
using Ichni.Menu.UI;
|
||
using Ichni.Story;
|
||
using Ichni.Story.UI;
|
||
using Ichni.UI;
|
||
using Sirenix.OdinInspector;
|
||
using SLSUtilities.WwiseAssistance;
|
||
using UniRx;
|
||
using UnityEngine;
|
||
using UnityEngine.SceneManagement;
|
||
using UnityEngine.Serialization;
|
||
|
||
namespace Ichni
|
||
{
|
||
public partial class MenuManager : MonoBehaviour
|
||
{
|
||
public static MenuManager instance;
|
||
|
||
public StartUIPage startUIPage;
|
||
public LoginPage loginPage;
|
||
public ChapterSelectionUIPage chapterSelectionUIPage;
|
||
public StoryUIPage storyUIPage;
|
||
public SelectionBoxUIPage selectionBoxUIPage;
|
||
// dialogUIPage 已随旧对话系统移除;阶段 3 将接入新的 VN 对话页面引用
|
||
public SongSelectionUIPage songSelectionUIPage;
|
||
public TransitionUIPage transitionUIPage;
|
||
public SettingsUIPage settingsUIPage;
|
||
|
||
public List<string> languageList;
|
||
public List<string> displayLanguageList;
|
||
}
|
||
|
||
public partial class MenuManager
|
||
{
|
||
AsyncOperation asyncOperation;
|
||
public bool isEnteringGame;
|
||
|
||
/// <summary>
|
||
/// 当前 MenuScene 是否已经完成 GameScene 预加载且尚未处于切场中。
|
||
/// TutorialFlowController 在写入“已处理”剧情变量前使用此状态进行最后一次启动前检查。
|
||
/// </summary>
|
||
public bool CanBeginGame => !isEnteringGame && asyncOperation != null;
|
||
|
||
private void Awake()
|
||
{
|
||
instance = this;
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
isEnteringGame = false;
|
||
|
||
InformationTransistor information = InformationTransistor.instance;
|
||
MenuReturnDestination returnDestination = information != null
|
||
? information.menuReturnDestination
|
||
: MenuReturnDestination.None;
|
||
|
||
if (returnDestination == MenuReturnDestination.SongSelection &&
|
||
information != null && information.chapter != null &&
|
||
information.song != null && information.difficulty != null)
|
||
{
|
||
startUIPage.mainCanvasGroup.gameObject.SetActive(false);
|
||
ChapterSelectionManager.instance.currentChapter =
|
||
information.chapter;
|
||
AudioManager.SetSwitch(ChapterSelectionManager.instance.currentChapter.chapterSwitch);
|
||
MenuInformationRecorder.instance.songSelectionRecords[
|
||
ChapterSelectionManager.instance.currentChapter] =
|
||
new SongSelectionRecord(information.song, information.difficulty);
|
||
songSelectionUIPage.FadeIn();
|
||
}
|
||
else if (returnDestination == MenuReturnDestination.Story &&
|
||
information != null && information.chapter != null)
|
||
{
|
||
startUIPage.mainCanvasGroup.gameObject.SetActive(false);
|
||
ChapterSelectionManager.instance.currentChapter = information.chapter;
|
||
AudioManager.SetSwitch(ChapterSelectionManager.instance.currentChapter.chapterSwitch);
|
||
|
||
// MenuScene 会在教程游玩后重新创建,必须显式重建章节故事树,
|
||
// 不能依赖旧场景中残留的 Block 实例。
|
||
StoryManager.instance?.OpenChapter(ChapterSelectionManager.instance.currentChapter.chapterIndex);
|
||
storyUIPage.FadeIn();
|
||
}
|
||
|
||
// 返回目标是一次性运行态信息。无论是否能恢复页面,都不能让它在下次重进菜单时重复生效。
|
||
information?.ClearMenuReturnDestination();
|
||
|
||
Application.targetFrameRate = SettingsManager.instance.gameSettings.targetFrame;
|
||
asyncOperation = SceneManager.LoadSceneAsync("GameScene");
|
||
asyncOperation.allowSceneActivation = false;
|
||
}
|
||
}
|
||
|
||
public partial class MenuManager
|
||
{
|
||
public void EnterGame()
|
||
{
|
||
EnterGame(MenuReturnDestination.SongSelection);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 激活已预加载的 GameScene,并写入唯一的菜单返回目标。
|
||
/// 普通选曲使用 <see cref="MenuReturnDestination.SongSelection"/>,教程使用
|
||
/// <see cref="MenuReturnDestination.Story"/>。
|
||
/// </summary>
|
||
public void EnterGame(MenuReturnDestination returnDestination)
|
||
{
|
||
InformationTransistor.instance?.SetMenuReturnDestination(returnDestination);
|
||
EnterGameScene();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 为 TutorialBlock 等非选曲入口准备上下文并播放通用转场。
|
||
/// 运行成功后会返回 true;返回 false 时不会修改剧情变量或存档,调用方应保留原状。
|
||
/// </summary>
|
||
public bool TryBeginGame(ChapterSelectionUnit chapter, SongItemData song,
|
||
DifficultyData difficulty, MenuReturnDestination returnDestination, UIPageBase sourcePage)
|
||
{
|
||
if (!CanBeginGame)
|
||
{
|
||
Debug.LogWarning("[MenuManager] GameScene 未完成预加载或菜单已在切换,忽略启动请求。");
|
||
return false;
|
||
}
|
||
|
||
if (InformationTransistor.instance == null ||
|
||
!InformationTransistor.instance.PrepareGameLaunch(chapter, song, difficulty, returnDestination))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
isEnteringGame = true;
|
||
sourcePage?.FadeOut();
|
||
transitionUIPage?.FadeIn();
|
||
AudioManager.Post(AK.EVENTS.ENTERTOGAME);
|
||
|
||
Observable.Timer(TimeSpan.FromSeconds(0.6f)).Subscribe(_ => EnterGameScene());
|
||
return true;
|
||
}
|
||
|
||
public void EnterGameScene()
|
||
{
|
||
if (asyncOperation == null)
|
||
{
|
||
Debug.LogError("[MenuManager] GameScene 尚未完成预加载,无法进入游戏。");
|
||
isEnteringGame = false;
|
||
return;
|
||
}
|
||
|
||
MenuInputManager.instance?.gameInput?.Menu.Disable();
|
||
asyncOperation.allowSceneActivation = true;
|
||
}
|
||
}
|
||
}
|