using System; using AppleHills.Data.CardSystem; using Core; using TMPro; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; #if UNITY_EDITOR using UnityEditor; #endif namespace UI.CardSystem { /// /// Displays a single card using the new visual system with frames, overlays, backgrounds, and zone shapes. /// public class CardDisplay : MonoBehaviour, IPointerClickHandler { [Header("UI Elements")] [SerializeField] private TextMeshProUGUI cardNameText; [SerializeField] private Image cardImage; [SerializeField] private Image frameImage; [SerializeField] private Image overlayImage; [SerializeField] private Image backgroundImage; [SerializeField] private Image zoneShapeImage; [Header("Card Data")] [SerializeField] private CardData cardData; [Header("Visual Settings")] [SerializeField] private CardVisualConfig visualConfig; #if UNITY_EDITOR [Header("Editor Tools")] [SerializeField] private CardDefinition editorCardDefinition; #endif // Events public event Action OnCardClicked; // Preview mode tracking for click forwarding private bool _isPreviewMode; private AlbumCardSlot _previewSlot; /// /// Sets up the card display with the given card data /// public void SetupCard(CardData data) { if (data == null) { Logging.Warning("[CardDisplay] Attempted to setup card with null data"); return; } cardData = data; UpdateCardVisuals(); } /// /// Updates all visual elements based on current card data /// private void UpdateCardVisuals() { if (cardData == null) { ClearCard(); return; } if (visualConfig == null) { Logging.Warning("[CardDisplay] No CardVisualConfig assigned. Visuals may not display correctly."); } // Update text UpdateCardName(); // Update main card image UpdateCardImage(); // Update rarity-based visuals (frame and overlay) UpdateRarityVisuals(); // Update zone-based visuals (background and shape) UpdateZoneVisuals(); Logging.Debug($"[CardDisplay] Updated visuals for card: {cardData.Name} (Rarity: {cardData.Rarity}, Zone: {cardData.Zone})"); } /// /// Apply preview visuals - black tint to card image and question marks for name /// Used for empty slot previews to show locked/unknown cards /// public void SetPreviewVisuals() { // Set card name to question marks if (cardNameText != null) { cardNameText.text = "??????"; } // Apply black non-opaque tint to card image if (cardImage != null) { cardImage.color = Color.black; } Logging.Debug($"[CardDisplay] Applied preview visuals (black tint and ?????? name)"); } /// /// Reset preview visuals back to normal /// public void ClearPreviewVisuals() { // Restore normal card name if (cardData != null && cardNameText != null) { cardNameText.text = cardData.Name ?? "Unknown Card"; } // Reset card image color to white (normal) if (cardImage != null) { cardImage.color = Color.white; } Logging.Debug($"[CardDisplay] Cleared preview visuals"); } /// /// Updates the card name text /// private void UpdateCardName() { if (cardNameText != null) { cardNameText.text = cardData.Name ?? "Unknown Card"; } } /// /// Updates the main card image /// private void UpdateCardImage() { if (cardImage != null) { if (cardData.CardImage != null) { cardImage.sprite = cardData.CardImage; cardImage.enabled = true; } else { cardImage.sprite = null; cardImage.enabled = false; } } } /// /// Updates frame and overlay based on card rarity /// private void UpdateRarityVisuals() { if (visualConfig == null) return; // Update frame if (frameImage != null) { Sprite frameSprite = visualConfig.GetRarityFrame(cardData.Rarity); if (frameSprite != null) { frameImage.sprite = frameSprite; frameImage.enabled = true; } else { frameImage.enabled = false; } } // Update overlay (can be null for some rarities) if (overlayImage != null) { Sprite overlaySprite = visualConfig.GetRarityOverlay(cardData.Rarity); if (overlaySprite != null) { overlayImage.sprite = overlaySprite; overlayImage.enabled = true; } else { overlayImage.enabled = false; } } } /// /// Updates background and zone shape based on card zone and rarity /// Special handling for Legendary cards /// private void UpdateZoneVisuals() { if (visualConfig == null) return; // Update background // Legendary cards get special background, others get zone background if (backgroundImage != null) { Sprite bgSprite = visualConfig.GetBackground(cardData.Zone, cardData.Rarity); if (bgSprite != null) { backgroundImage.sprite = bgSprite; backgroundImage.enabled = true; } else { backgroundImage.enabled = false; } } // Update zone shape // Legendary cards don't show shapes if (zoneShapeImage != null) { Sprite shapeSprite = visualConfig.GetZoneShape(cardData.Zone, cardData.Rarity); if (shapeSprite != null) { zoneShapeImage.sprite = shapeSprite; zoneShapeImage.enabled = true; } else { zoneShapeImage.enabled = false; } } } /// /// Clears all visual elements /// private void ClearCard() { if (cardNameText != null) cardNameText.text = ""; if (cardImage != null) cardImage.enabled = false; if (frameImage != null) frameImage.enabled = false; if (overlayImage != null) overlayImage.enabled = false; if (backgroundImage != null) backgroundImage.enabled = false; if (zoneShapeImage != null) zoneShapeImage.enabled = false; } /// /// Called when the card is clicked /// public void OnClick() { OnCardClicked?.Invoke(this); } /// /// Returns the card data associated with this display /// public CardData GetCardData() { return cardData; } /// /// Updates the visual config reference /// public void SetVisualConfig(CardVisualConfig config) { visualConfig = config; if (cardData != null) { UpdateCardVisuals(); } } /// /// Enable preview mode - when clicked, forwards click to the associated slot /// public void SetPreviewMode(bool isEnabled, AlbumCardSlot slot = null) { _isPreviewMode = isEnabled; _previewSlot = slot; // Enable raycast targets on images so this CardDisplay can receive clicks if (cardImage != null) cardImage.raycastTarget = isEnabled; if (frameImage != null) frameImage.raycastTarget = isEnabled; if (overlayImage != null) overlayImage.raycastTarget = isEnabled; if (backgroundImage != null) backgroundImage.raycastTarget = isEnabled; if (zoneShapeImage != null) zoneShapeImage.raycastTarget = isEnabled; Logging.Debug($"[CardDisplay] Preview mode {(isEnabled ? "enabled" : "disabled")}, slot: {(slot != null ? slot.name : "NULL")}"); } /// /// Handle click on CardDisplay - forward to preview slot if in preview mode /// public void OnPointerClick(PointerEventData eventData) { Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] OnPointerClick on {name}, _isPreviewMode={_isPreviewMode}, _previewSlot={((_previewSlot != null) ? _previewSlot.name : "NULL")}"); if (_isPreviewMode && _previewSlot != null) { Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - In preview mode, calling DismissPreview on slot: {_previewSlot.name}"); _previewSlot.DismissPreview(); } else { // Not in preview mode - forward click to parent AlbumCard (if it exists) AlbumCard parentAlbumCard = GetComponentInParent(); if (parentAlbumCard != null) { Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - Forwarding click to parent AlbumCard"); parentAlbumCard.OnPointerClick(eventData); } else { Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - No parent AlbumCard, firing OnCardClicked event"); OnCardClicked?.Invoke(this); } } } #if UNITY_EDITOR /// /// Editor-only: Preview a card from the assigned definition /// public void PreviewFromDefinition() { if (editorCardDefinition == null) { UnityEngine.Debug.LogWarning("[CardDisplay] No Card Definition assigned in Editor Tools."); return; } CardData previewData = editorCardDefinition.CreateCardData(); SetupCard(previewData); } /// /// Editor-only: Clear the preview /// public void ClearPreview() { cardData = null; ClearCard(); } #endif } #if UNITY_EDITOR [CustomEditor(typeof(CardDisplay))] public class CardDisplayEditor : Editor { public override void OnInspectorGUI() { DrawDefaultInspector(); CardDisplay display = (CardDisplay)target; EditorGUILayout.Space(); EditorGUILayout.LabelField("Editor Preview Tools", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Preview Card")) { display.PreviewFromDefinition(); EditorUtility.SetDirty(display); } if (GUILayout.Button("Clear Preview")) { display.ClearPreview(); EditorUtility.SetDirty(display); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.HelpBox( "Assign a Card Definition in 'Editor Tools' section, then click 'Preview Card' to see how it will look at runtime.", MessageType.Info ); } } #endif }