207 lines
6.4 KiB
C#
207 lines
6.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using AibisDream.Framework;
|
|
using AibisDream.Kit;
|
|
using AibisDream.SaveSystem;
|
|
using UnityEngine;
|
|
using UnityEngine.Playables;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using Yarn.Unity;
|
|
|
|
namespace AibisDream
|
|
{
|
|
public class SubwayCenter : Singleton<SubwayCenter>, ISceneDialogueGate
|
|
{
|
|
#region 部分索引
|
|
|
|
public SpriteRenderer newsSpriteRenderer;
|
|
|
|
public PlayableDirector arriveStation;
|
|
|
|
public static StateMachine<OutSideState> StateMachine { get; private set; }
|
|
|
|
public bool IsDialogueReady { get; private set; }
|
|
|
|
private string _currentNewsSpriteId;
|
|
|
|
#endregion
|
|
|
|
public override void OnSingletonInit()
|
|
{
|
|
StateMachine = new StateMachine<OutSideState>(CreateState);
|
|
IsDialogueReady = false;
|
|
StartCoroutine(InitStateMachineRoutine());
|
|
}
|
|
|
|
private IEnumerator InitStateMachineRoutine()
|
|
{
|
|
IsDialogueReady = false;
|
|
yield return StateMachine.Init(OutSideState.Subway);
|
|
IsDialogueReady = true;
|
|
}
|
|
|
|
public override void OnSingletonDestroy()
|
|
{
|
|
IsDialogueReady = false;
|
|
}
|
|
|
|
private static IState<OutSideState> CreateState(OutSideState nextState, string arg = "")
|
|
{
|
|
IState<OutSideState> res = nextState switch
|
|
{
|
|
OutSideState.Subway => new SubwayState(),
|
|
OutSideState.SubwayTV => new SubwayTVState(),
|
|
_ => throw new ArgumentOutOfRangeException(nameof(nextState), nextState, null)
|
|
};
|
|
|
|
res.SetArgs(arg);
|
|
return res;
|
|
}
|
|
|
|
public IEnumerator ArriveAtStation()
|
|
{
|
|
arriveStation.Play();
|
|
yield return new WaitForSeconds((float) arriveStation.playableAsset.duration);
|
|
}
|
|
|
|
public IEnumerator SwitchNews(string spriteId)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(spriteId))
|
|
{
|
|
Debug.LogWarning("[SubwayCenter] spriteId 为空,无法切换新闻图片。");
|
|
yield break;
|
|
}
|
|
|
|
string addressableKey = $"Sprite/News[{spriteId}]";
|
|
var handle = ResourceSystem.LoadAsync<Sprite>(addressableKey);
|
|
yield return handle;
|
|
|
|
if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null)
|
|
{
|
|
Debug.LogError($"[SubwayCenter] 加载新闻图片失败: {addressableKey}");
|
|
yield break;
|
|
}
|
|
|
|
if (newsSpriteRenderer == null)
|
|
{
|
|
Debug.LogWarning("[SubwayCenter] newsSpriteRenderer 未赋值,无法切换新闻图片。");
|
|
yield break;
|
|
}
|
|
|
|
newsSpriteRenderer.sprite = handle.Result;
|
|
_currentNewsSpriteId = spriteId;
|
|
}
|
|
|
|
/// <summary>Captures the macro subway scene snapshot.</summary>
|
|
public SubwaySnapshotDto CaptureSnapshot()
|
|
{
|
|
if (StateMachine == null || !StateMachine.HasState)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new SubwaySnapshotDto
|
|
{
|
|
state = StateMachine.CurState.ToString(),
|
|
args = "",
|
|
newsSpriteId = _currentNewsSpriteId
|
|
};
|
|
}
|
|
|
|
/// <summary>Restores the macro subway scene snapshot by jumping directly to the target state.</summary>
|
|
public IEnumerator RestoreSnapshot(SubwaySnapshotDto dto)
|
|
{
|
|
if (dto == null || string.IsNullOrEmpty(dto.state))
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
if (!Enum.TryParse<OutSideState>(dto.state, out var state))
|
|
{
|
|
Debug.LogWarning($"[SubwayCenter] Could not parse OutSideState: {dto.state}");
|
|
yield break;
|
|
}
|
|
|
|
yield return StateMachine.SwitchStateImmediate(state, dto.args ?? "");
|
|
|
|
if (!string.IsNullOrEmpty(dto.newsSpriteId))
|
|
{
|
|
yield return SwitchNews(dto.newsSpriteId);
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct SubwayState : IState<OutSideState>
|
|
{
|
|
public OutSideState GetState => OutSideState.Subway;
|
|
|
|
public IEnumerator Enter()
|
|
{
|
|
yield return CameraKit.Instance.SwitchCamera(CameraEnum.Subway);
|
|
DialogUIManager.Instance.LoadBubbles(BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.Subway));
|
|
}
|
|
|
|
public IEnumerator EnterImmediate()
|
|
{
|
|
yield return CameraKit.Instance.SwitchCamera(CameraEnum.Subway, true);
|
|
DialogUIManager.Instance.LoadBubbles(BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.Subway));
|
|
}
|
|
}
|
|
|
|
public struct SubwayTVState : IState<OutSideState>
|
|
{
|
|
public OutSideState GetState => OutSideState.SubwayTV;
|
|
|
|
public IEnumerator Enter()
|
|
{
|
|
yield return CameraKit.Instance.SwitchCamera(CameraEnum.SubwayTV);
|
|
// 要加载气泡吗?
|
|
DialogUIManager.Instance.LoadBubbles(BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.SubwayTV));
|
|
}
|
|
|
|
public IEnumerator EnterImmediate()
|
|
{
|
|
yield return CameraKit.Instance.SwitchCamera(CameraEnum.SubwayTV, true);
|
|
DialogUIManager.Instance.LoadBubbles(BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.SubwayTV));
|
|
}
|
|
}
|
|
|
|
public enum OutSideState
|
|
{
|
|
Subway,
|
|
SubwayTV
|
|
}
|
|
|
|
public static class SubwayYarnCommand
|
|
{
|
|
[YarnCommand("switch_outside_to")]
|
|
public static IEnumerator SwitchOutsideTo(string targetStateStr)
|
|
{
|
|
if (!Enum.TryParse(targetStateStr, out OutSideState targetState))
|
|
{
|
|
Debug.Log($"{targetStateStr}不在OutSideState枚举中");
|
|
yield break;
|
|
}
|
|
|
|
yield return SubwayCenter.StateMachine.SwitchState(targetState);
|
|
}
|
|
|
|
[YarnCommand("arrive_at_station")]
|
|
public static IEnumerator ArriveAtStation()
|
|
{
|
|
return SubwayCenter.Instance.ArriveAtStation();
|
|
}
|
|
|
|
[YarnCommand("switch_news")]
|
|
public static IEnumerator SwitchNews(string spriteId)
|
|
{
|
|
if (SubwayCenter.Instance == null)
|
|
{
|
|
Debug.LogError("[SubwayYarnCommand] SubwayCenter 实例不存在。");
|
|
yield break;
|
|
}
|
|
|
|
yield return SubwayCenter.Instance.SwitchNews(spriteId);
|
|
}
|
|
}
|
|
} |