#if UNITY_EDITOR using UnityEditor; using UnityEngine; using Data.CardSystem; using AppleHills.Data.CardSystem; using System.Collections.Generic; using System.Linq; namespace AppleHills.Editor { /// /// Live preview window for the Card System. Shows real-time collection status. /// public class CardSystemLivePreview : EditorWindow { private Vector2 scrollPosition; private bool isSubscribed = false; private double lastUpdateTime = 0; private const double UPDATE_INTERVAL = 1.0; // Poll every 1 second as backup // Cache for display private Dictionary> cardsByRarity = new Dictionary>(); private List pendingCards = new List(); private int totalCards = 0; private int totalUniqueCards = 0; private int totalPendingCards = 0; private int boosterCount = 0; private string lastEventMessage = ""; [MenuItem("AppleHills/Cards/Live Collection Preview")] public static void ShowWindow() { CardSystemLivePreview window = GetWindow("Card Collection Live"); window.minSize = new Vector2(400, 300); window.Show(); } private void OnEnable() { EditorApplication.playModeStateChanged += OnPlayModeStateChanged; if (Application.isPlaying) { SubscribeToEvents(); RefreshData(); } } private void OnDisable() { EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; UnsubscribeFromEvents(); } private void OnPlayModeStateChanged(PlayModeStateChange state) { if (state == PlayModeStateChange.EnteredPlayMode) { SubscribeToEvents(); RefreshData(); } else if (state == PlayModeStateChange.ExitingPlayMode) { UnsubscribeFromEvents(); } } private void SubscribeToEvents() { if (isSubscribed || !Application.isPlaying) return; if (CardSystemManager.Instance != null) { CardSystemManager.Instance.OnBoosterOpened += OnBoosterOpened; CardSystemManager.Instance.OnCardCollected += OnCardCollected; CardSystemManager.Instance.OnBoosterCountChanged += OnBoosterCountChanged; CardSystemManager.Instance.OnPendingCardAdded += OnPendingCardAdded; CardSystemManager.Instance.OnPendingCardRemoved += OnPendingCardRemoved; isSubscribed = true; Debug.Log("[CardSystemLivePreview] Subscribed to CardSystemManager events"); } } private void UnsubscribeFromEvents() { if (!isSubscribed) return; if (CardSystemManager.Instance != null) { CardSystemManager.Instance.OnBoosterOpened -= OnBoosterOpened; CardSystemManager.Instance.OnCardCollected -= OnCardCollected; CardSystemManager.Instance.OnBoosterCountChanged -= OnBoosterCountChanged; CardSystemManager.Instance.OnPendingCardAdded -= OnPendingCardAdded; CardSystemManager.Instance.OnPendingCardRemoved -= OnPendingCardRemoved; } isSubscribed = false; } // Event Handlers private void OnBoosterOpened(List cards) { lastEventMessage = $"Booster opened! Drew {cards.Count} cards"; RefreshData(); Repaint(); } private void OnCardCollected(CardData card) { lastEventMessage = $"New card collected: {card.Name} ({card.Rarity})"; RefreshData(); Repaint(); } private void OnBoosterCountChanged(int count) { boosterCount = count; lastEventMessage = $"Booster count changed: {count}"; Repaint(); } private void OnPendingCardAdded(CardData card) { lastEventMessage = $"Pending card added: {card.Name} ({card.Rarity})"; RefreshData(); Repaint(); } private void OnPendingCardRemoved(CardData card) { lastEventMessage = $"Card removed from pending: {card.Name} ({card.Rarity}) - being placed"; RefreshData(); Repaint(); } private void RefreshData() { if (!Application.isPlaying || CardSystemManager.Instance == null) return; // Get ONLY collected cards (not pending) to avoid duplicates var collectedCards = CardSystemManager.Instance.GetCollectionOnly(); // Group by rarity cardsByRarity.Clear(); cardsByRarity[CardRarity.Normal] = collectedCards.Where(c => c.Rarity == CardRarity.Normal).ToList(); cardsByRarity[CardRarity.Rare] = collectedCards.Where(c => c.Rarity == CardRarity.Rare).ToList(); cardsByRarity[CardRarity.Legendary] = collectedCards.Where(c => c.Rarity == CardRarity.Legendary).ToList(); totalCards = collectedCards.Sum(c => c.CopiesOwned); totalUniqueCards = collectedCards.Count; boosterCount = CardSystemManager.Instance.GetBoosterPackCount(); // Get pending cards separately pendingCards = CardSystemManager.Instance.GetPendingRevealCards(); totalPendingCards = pendingCards.Count; } private void Update() { if (!Application.isPlaying) return; // Poll every second as backup (in case events are missed) if (EditorApplication.timeSinceStartup - lastUpdateTime > UPDATE_INTERVAL) { lastUpdateTime = EditorApplication.timeSinceStartup; if (!isSubscribed) { SubscribeToEvents(); } RefreshData(); Repaint(); } } private void OnGUI() { if (!Application.isPlaying) { EditorGUILayout.HelpBox("Enter Play Mode to view live collection data.", MessageType.Info); return; } if (CardSystemManager.Instance == null) { EditorGUILayout.HelpBox("CardSystemManager instance not found!", MessageType.Warning); return; } // Header EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Label("Live Collection Preview", EditorStyles.boldLabel); EditorGUILayout.Space(); // Summary Stats EditorGUILayout.LabelField("Total Unique Cards:", totalUniqueCards.ToString()); EditorGUILayout.LabelField("Total Cards Owned:", totalCards.ToString()); EditorGUILayout.LabelField("Booster Packs:", boosterCount.ToString()); EditorGUILayout.LabelField("Pending Reveal:", totalPendingCards.ToString(), EditorStyles.boldLabel); if (!string.IsNullOrEmpty(lastEventMessage)) { EditorGUILayout.Space(); EditorGUILayout.HelpBox(lastEventMessage, MessageType.Info); } EditorGUILayout.EndVertical(); EditorGUILayout.Space(); // Collection by Rarity scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); // Pending Cards Section if (totalPendingCards > 0) { DrawPendingCardsSection(); EditorGUILayout.Space(); } DrawRaritySection(CardRarity.Legendary, Color.yellow); DrawRaritySection(CardRarity.Rare, new Color(0.5f, 0.5f, 1f)); // Light blue DrawRaritySection(CardRarity.Normal, Color.white); EditorGUILayout.EndScrollView(); EditorGUILayout.Space(); // Actions EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Refresh Now")) { RefreshData(); } if (GUILayout.Button("Clear Event Log")) { lastEventMessage = ""; } EditorGUILayout.EndHorizontal(); } private void DrawPendingCardsSection() { var oldColor = GUI.backgroundColor; GUI.backgroundColor = new Color(1f, 0.8f, 0.4f); // Orange tint for pending EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUI.backgroundColor = oldColor; GUILayout.Label($"⏳ Pending Reveal ({pendingCards.Count} cards)", EditorStyles.boldLabel); // Group pending by rarity for display var pendingByRarity = pendingCards.GroupBy(c => c.Rarity).OrderByDescending(g => g.Key); foreach (var rarityGroup in pendingByRarity) { EditorGUILayout.Space(5); var rarityColor = GetRarityColor(rarityGroup.Key); oldColor = GUI.color; GUI.color = rarityColor; GUILayout.Label($"{rarityGroup.Key} ({rarityGroup.Count()})", EditorStyles.miniBoldLabel); GUI.color = oldColor; foreach (var card in rarityGroup.OrderBy(c => c.Name)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(" • " + card.Name, GUILayout.Width(200)); EditorGUILayout.LabelField(card.Zone.ToString(), GUILayout.Width(100)); EditorGUILayout.LabelField($"Copies: {card.CopiesOwned}", GUILayout.Width(80)); EditorGUILayout.EndHorizontal(); } } EditorGUILayout.EndVertical(); } private Color GetRarityColor(CardRarity rarity) { switch (rarity) { case CardRarity.Legendary: return Color.yellow; case CardRarity.Rare: return new Color(0.5f, 0.5f, 1f); case CardRarity.Normal: return Color.white; default: return Color.gray; } } private void DrawRaritySection(CardRarity rarity, Color color) { if (!cardsByRarity.ContainsKey(rarity) || cardsByRarity[rarity].Count == 0) return; var cards = cardsByRarity[rarity]; int totalCopies = cards.Sum(c => c.CopiesOwned); EditorGUILayout.Space(); // Header var oldColor = GUI.backgroundColor; GUI.backgroundColor = color; EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUI.backgroundColor = oldColor; GUILayout.Label($"{rarity} ({cards.Count} unique, {totalCopies} total)", EditorStyles.boldLabel); // Cards foreach (var card in cards.OrderBy(c => c.Name)) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(card.Name, GUILayout.Width(200)); EditorGUILayout.LabelField($"x{card.CopiesOwned}", GUILayout.Width(50)); EditorGUILayout.LabelField(card.Zone.ToString(), GUILayout.Width(100)); // Progress to next tier (if not Legendary) if (rarity < CardRarity.Legendary) { int copiesNeeded = 5; float progress = Mathf.Clamp01((float)card.CopiesOwned / copiesNeeded); Rect progressRect = GUILayoutUtility.GetRect(100, 18); EditorGUI.ProgressBar(progressRect, progress, $"{card.CopiesOwned}/{copiesNeeded}"); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); } } } #endif