Files
aibis-dream/Assets/Scripts/MiniGame/Tarot/TarotManager.cs
T

218 lines
6.8 KiB
C#

using System.Collections;
using AibisDream;
using AibisDream.FixSystem;
using AibisDream.Framework;
using UnityEngine;
namespace AibisDream.MiniGame.Tarot
{
public class TarotManager : MonoBehaviour
{
[Header("View")]
[Tooltip("Root view object (toggled on/off)")]
[SerializeField] private GameObject tarotView;
[Header("Sprites")]
[SerializeField] private Sprite frontSprite;
[SerializeField] private Sprite backSprite;
[Header("Dialogue Bubbles")]
[Tooltip("退出塔罗时恢复的气泡槽位;不填则尝试 Outside / BodyModule。")]
[SerializeField] private BubbleSlotGroup restoreBubbleSlotGroup;
private TarotDeck _deck;
private bool _isCardSelected;
private int _selectedIndex = -1;
private BubbleSlotGroupData _savedBubbleData;
private bool _bubbleSwapActive;
public TarotDeck Deck => _deck;
public bool IsCardSelected => _isCardSelected;
public int SelectedIndex => _selectedIndex;
public TarotCard SelectedCard => _deck != null ? _deck.SelectedCard : null;
private void Start()
{
FixSystemCenter.SystemDic.Register(this);
FindDeck();
FindView();
if (tarotView != null) tarotView.SetActive(false);
}
private void FindDeck()
{
if (_deck != null) return;
_deck = GetComponentInChildren<TarotDeck>(true);
if (_deck == null)
Debug.LogWarning("[TarotManager] TarotDeck not found in children", this);
}
private void FindView()
{
if (tarotView != null) return;
var t = transform.Find("TarotView");
if (t != null) tarotView = t.gameObject;
}
#region View Control
public void OpenView()
{
FindView();
if (tarotView != null) tarotView.SetActive(true);
gameObject.SetActive(true);
}
public void CloseView()
{
if (tarotView != null) tarotView.SetActive(false);
}
#endregion
#region Tarot Flow
/// <param name="fadeInDuration">null 时使用 TarotDeck 上配置的淡入时长</param>
public IEnumerator ShowDeck(int cardCount, float? fadeInDuration = null)
{
_isCardSelected = false;
_selectedIndex = -1;
OpenView();
FindDeck();
if (_deck == null)
{
Debug.LogError("[TarotManager] Cannot show deck: TarotDeck is null", this);
yield break;
}
_deck.OnCardSelected -= OnCardSelected;
_deck.OnCardSelected += OnCardSelected;
TryEnterTarotBubbleMode();
if (backSprite == null)
Debug.LogWarning(
"[TarotManager] Back Sprite 未赋值,流程生成的牌将沿用预制体 SpriteRenderer 上的图;若预制体也为空则会不可见。请在 Inspector 指定 Back / Front Sprite。",
this);
if (frontSprite == null)
Debug.LogWarning("[TarotManager] Front Sprite 未赋值,<<flip_tarot>> 翻正面时可能无图。", this);
_deck.Setup(cardCount, frontSprite, backSprite);
yield return _deck.FadeInStack(fadeInDuration);
}
public IEnumerator SpreadCards()
{
if (_deck == null) yield break;
yield return _deck.SpreadCards();
}
public void EnableSelection()
{
_isCardSelected = false;
_selectedIndex = -1;
_deck?.SetInteractable(true);
}
public IEnumerator WaitForSelection()
{
EnableSelection();
while (!_isCardSelected)
yield return null;
}
public IEnumerator FlipSelectedCard(TarotOrientation orientation, float duration = 0.5f)
{
var card = _deck?.SelectedCard;
if (card == null)
{
Debug.LogWarning("[TarotManager] No card selected to flip", this);
yield break;
}
yield return card.Flip(orientation, duration);
}
public IEnumerator RotateSelectedCard(TarotOrientation orientation, float duration = 0.7f)
{
var card = _deck?.SelectedCard;
if (card == null)
{
Debug.LogWarning("[TarotManager] No card selected to rotate", this);
yield break;
}
yield return card.SetOrientationAnimated(orientation, duration);
}
public IEnumerator HideAll(float duration = 0.3f)
{
if (_deck != null)
yield return _deck.HideAll(duration);
CloseView();
RestoreTarotBubbleMode();
}
#endregion
private void OnCardSelected(TarotCard card)
{
_isCardSelected = true;
_selectedIndex = card.Index;
YarnVariableStorage.Instance?.SetValue("$tarotSelectedIndex", (float)card.Index);
}
private void OnDestroy()
{
if (_deck != null)
_deck.OnCardSelected -= OnCardSelected;
RestoreTarotBubbleMode();
}
private void TryEnterTarotBubbleMode()
{
if (!BubbleSlotKit.Instance.TryGet(BubbleSlotEnum.Tarot, out _))
return;
var snapshot = CollectRestoreSnapshot();
if (snapshot.bubbleSlots == null || snapshot.bubbleSlots.Length == 0)
{
Debug.LogWarning(
"[TarotManager] 已配置 Tarot 气泡但无法取得有效的恢复快照(请指定 restoreBubbleSlotGroup 或保证 Outside/BodyModule 气泡已注册),跳过气泡切换。",
this);
return;
}
_savedBubbleData = snapshot;
_bubbleSwapActive = true;
BubbleSlotKit.Instance.LoadBubbles(BubbleSlotEnum.Tarot);
}
private void RestoreTarotBubbleMode()
{
if (!_bubbleSwapActive)
return;
_bubbleSwapActive = false;
DialogUIManager.Instance.LoadBubbles(_savedBubbleData);
}
private BubbleSlotGroupData CollectRestoreSnapshot()
{
if (restoreBubbleSlotGroup != null)
return restoreBubbleSlotGroup.CollectData();
if (BubbleSlotKit.Instance.TryGet(BubbleSlotEnum.Outside, out _))
return BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.Outside);
if (BubbleSlotKit.Instance.TryGet(BubbleSlotEnum.BodyModule, out _))
return BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.BodyModule);
return default;
}
}
}