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(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 /// null 时使用 TarotDeck 上配置的淡入时长 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 未赋值,<> 翻正面时可能无图。", 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; } } }