Update the card kerfufle

This commit is contained in:
Michal Pikulski
2025-11-11 20:25:23 +01:00
parent 06cc3bde3b
commit 1fdff3450b
28 changed files with 1259 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
using Core;
using Core.SaveLoad;
using UnityEngine;
using UnityEngine.EventSystems;
using UI.CardSystem.StateMachine;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Album enlarged state - card is enlarged when clicked from album slot.
/// Different from EnlargedNewState as it doesn't show "NEW" badge.
/// </summary>
public class CardAlbumEnlargedState : AppleState, IPointerClickHandler
{
private CardContext _context;
private Vector3 _originalScale;
private Transform _originalParent;
private Vector3 _originalLocalPosition;
private Quaternion _originalLocalRotation;
// Events for page to manage backdrop and reparenting
public event System.Action<CardAlbumEnlargedState> OnEnlargeRequested;
public event System.Action<CardAlbumEnlargedState> OnShrinkRequested;
private void Awake()
{
_context = GetComponentInParent<CardContext>();
}
public override void OnEnterState()
{
// Store original transform for restoration
_originalScale = _context.RootTransform.localScale;
_originalParent = _context.RootTransform.parent;
_originalLocalPosition = _context.RootTransform.localPosition;
_originalLocalRotation = _context.RootTransform.localRotation;
// Notify page to show backdrop and reparent card to top layer
OnEnlargeRequested?.Invoke(this);
// Enlarge the card
if (_context.Animator != null)
{
_context.Animator.PlayEnlarge();
}
Logging.Debug($"[CardAlbumEnlargedState] Card enlarged from album: {_context.CardData?.Name}");
}
public void OnPointerClick(PointerEventData eventData)
{
// Click to shrink back
Logging.Debug($"[CardAlbumEnlargedState] Card clicked while enlarged, shrinking back");
// Notify page to prepare for shrink
OnShrinkRequested?.Invoke(this);
// Shrink animation, then transition back
if (_context.Animator != null)
{
_context.Animator.PlayShrink(_originalScale, onComplete: () =>
{
_context.StateMachine.ChangeState("PlacedInSlotState");
});
}
}
/// <summary>
/// Get original parent for restoration
/// </summary>
public Transform GetOriginalParent() => _originalParent;
/// <summary>
/// Get original local position for restoration
/// </summary>
public Vector3 GetOriginalLocalPosition() => _originalLocalPosition;
/// <summary>
/// Get original local rotation for restoration
/// </summary>
public Quaternion GetOriginalLocalRotation() => _originalLocalRotation;
private void OnDisable()
{
// Restore original scale when exiting
if (_context?.RootTransform != null)
{
_context.RootTransform.localScale = _originalScale;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5f33526d9bb8458d8dc5ba41a88561da
timeCreated: 1762884900

View File

@@ -0,0 +1,73 @@
using Core.SaveLoad;
using UnityEngine;
using UnityEngine.EventSystems;
using Core;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Dragging state - handles card being dragged for album placement.
/// Integrates with existing drag/drop system.
/// </summary>
public class CardDraggingState : AppleState
{
[Header("Drag Settings")]
[SerializeField] private float dragScale = 1.1f;
private CardContext _context;
private Vector3 _originalScale;
private Vector3 _dragStartPosition;
private void Awake()
{
_context = GetComponentInParent<CardContext>();
}
public override void OnEnterState()
{
// Store original transform
_originalScale = _context.RootTransform.localScale;
_dragStartPosition = _context.RootTransform.position;
// Scale up slightly during drag for visual feedback
_context.RootTransform.localScale = _originalScale * dragScale;
Logging.Debug($"[CardDraggingState] Entered drag state for card: {_context.CardData?.Name}");
}
/// <summary>
/// Update drag position (called by external drag handler)
/// </summary>
public void UpdateDragPosition(Vector3 worldPosition)
{
_context.RootTransform.position = worldPosition;
}
/// <summary>
/// Called when drag is released and card snaps to slot
/// </summary>
public void OnDroppedInSlot()
{
_context.StateMachine.ChangeState("PlacedInSlotState");
}
/// <summary>
/// Called when drag is released but not over valid slot
/// </summary>
public void OnDroppedOutsideSlot()
{
// Return to revealed state
_context.StateMachine.ChangeState("RevealedState");
}
private void OnDisable()
{
// Restore original scale when exiting drag
if (_context?.RootTransform != null)
{
_context.RootTransform.localScale = _originalScale;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b17e4e1d7139446c9c4e0a813067331c
timeCreated: 1762884899

View File

@@ -0,0 +1,64 @@
using Core.SaveLoad;
using UnityEngine;
using UnityEngine.EventSystems;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Enlarged state for NEW cards - shows "NEW CARD" badge and waits for tap to dismiss.
/// Owns the NewCardBadge as a child GameObject.
/// </summary>
public class CardEnlargedNewState : AppleState, IPointerClickHandler
{
[Header("State-Owned Visuals")]
[SerializeField] private GameObject newCardBadge;
private CardContext _context;
private Vector3 _originalScale;
private void Awake()
{
_context = GetComponentInParent<CardContext>();
}
public override void OnEnterState()
{
// Store original scale
_originalScale = _context.RootTransform.localScale;
// Show NEW badge
if (newCardBadge != null)
{
newCardBadge.SetActive(true);
}
// Enlarge the card
if (_context.Animator != null)
{
_context.Animator.PlayEnlarge();
}
}
public void OnPointerClick(PointerEventData eventData)
{
// Tap to dismiss - shrink back and transition to revealed state
if (_context.Animator != null)
{
_context.Animator.PlayShrink(_originalScale, onComplete: () =>
{
_context.StateMachine.ChangeState("RevealedState");
});
}
}
private void OnDisable()
{
// Hide NEW badge when leaving state
if (newCardBadge != null)
{
newCardBadge.SetActive(false);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 698741a53f314b598af359a81d914ed3
timeCreated: 1762884651

View File

@@ -0,0 +1,86 @@
using Core.SaveLoad;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Enlarged state for REPEAT cards - shows progress bar toward next rarity upgrade.
/// Owns the ProgressBarUI as a child GameObject.
/// </summary>
public class CardEnlargedRepeatState : AppleState, IPointerClickHandler
{
[Header("State-Owned Visuals")]
[SerializeField] private GameObject progressBarContainer;
[SerializeField] private Image progressBarFill;
[SerializeField] private TextMeshProUGUI progressText;
[SerializeField] private int cardsToUpgrade = 5;
private CardContext _context;
private Vector3 _originalScale;
private void Awake()
{
_context = GetComponentInParent<CardContext>();
}
public override void OnEnterState()
{
// Store original scale
_originalScale = _context.RootTransform.localScale;
// Show progress bar
if (progressBarContainer != null)
{
progressBarContainer.SetActive(true);
UpdateProgressBar();
}
// Enlarge the card
if (_context.Animator != null)
{
_context.Animator.PlayEnlarge();
}
}
private void UpdateProgressBar()
{
int currentCount = _context.RepeatCardCount;
float progress = (float)currentCount / cardsToUpgrade;
if (progressBarFill != null)
{
progressBarFill.fillAmount = progress;
}
if (progressText != null)
{
progressText.text = $"{currentCount}/{cardsToUpgrade}";
}
}
public void OnPointerClick(PointerEventData eventData)
{
// Tap to dismiss - shrink back and transition to revealed state
if (_context.Animator != null)
{
_context.Animator.PlayShrink(_originalScale, onComplete: () =>
{
_context.StateMachine.ChangeState("RevealedState");
});
}
}
private void OnDisable()
{
// Hide progress bar when leaving state
if (progressBarContainer != null)
{
progressBarContainer.SetActive(false);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 257f0c81caa14481812a8ca0397bf567
timeCreated: 1762884651

View File

@@ -0,0 +1,81 @@
using Core.SaveLoad;
using UnityEngine;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Flipping state - handles the card flip animation from back to front.
/// Owns the CardBackVisual as a child GameObject.
/// </summary>
public class CardFlippingState : AppleState
{
[Header("State-Owned Visuals")]
[SerializeField] private GameObject cardBackVisual;
private CardContext _context;
private void Awake()
{
_context = GetComponentInParent<CardContext>();
}
public override void OnEnterState()
{
// Activate card back, hide card front
if (cardBackVisual != null)
{
cardBackVisual.SetActive(true);
}
if (_context.CardDisplay != null)
{
_context.CardDisplay.gameObject.SetActive(false);
}
// Play flip animation + scale punch
if (_context.Animator != null)
{
_context.Animator.PlayFlip(
cardBack: cardBackVisual.transform,
cardFront: _context.CardDisplay.transform,
onComplete: OnFlipComplete
);
_context.Animator.PlayFlipScalePunch();
}
}
private void OnFlipComplete()
{
// Transition based on whether this is a new card or repeat
if (_context.IsNewCard)
{
_context.StateMachine.ChangeState("EnlargedNewState");
}
else if (_context.RepeatCardCount > 0)
{
_context.StateMachine.ChangeState("EnlargedRepeatState");
}
else
{
_context.StateMachine.ChangeState("RevealedState");
}
}
private void OnDisable()
{
// Hide card back when leaving state
if (cardBackVisual != null)
{
cardBackVisual.SetActive(false);
}
// Ensure card front is visible
if (_context?.CardDisplay != null)
{
_context.CardDisplay.gameObject.SetActive(true);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7223d6cab8d94f74b00a6a538291850a
timeCreated: 1762884650

View File

@@ -0,0 +1,118 @@
using Core.SaveLoad;
using Pixelplacement.TweenSystem;
using UnityEngine;
using UnityEngine.EventSystems;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Idle state - card back is showing with gentle hover animation.
/// Waiting for click to flip and reveal.
/// Based on FlippableCard's idle behavior.
/// </summary>
public class CardIdleState : AppleState, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
{
[Header("State-Owned Visuals")]
[SerializeField] private GameObject cardBackVisual;
[Header("Idle Hover Settings")]
[SerializeField] private bool enableIdleHover = true;
[SerializeField] private float idleHoverHeight = 10f;
[SerializeField] private float idleHoverDuration = 1.5f;
[SerializeField] private float hoverScaleMultiplier = 1.05f;
private CardContext _context;
private TweenBase _idleHoverTween;
private Vector2 _originalPosition;
private void Awake()
{
_context = GetComponentInParent<CardContext>();
}
public override void OnEnterState()
{
// Show card back, hide card front
if (cardBackVisual != null)
{
cardBackVisual.SetActive(true);
// Ensure card back is at 0° rotation (facing camera)
cardBackVisual.transform.localRotation = Quaternion.Euler(0, 0, 0);
}
if (_context.CardDisplay != null)
{
_context.CardDisplay.gameObject.SetActive(false);
// Ensure card front starts at 180° rotation (flipped away)
_context.CardDisplay.transform.localRotation = Quaternion.Euler(0, 180, 0);
}
// Save original position for hover animation
RectTransform rectTransform = _context.RootTransform.GetComponent<RectTransform>();
if (rectTransform != null)
{
_originalPosition = rectTransform.anchoredPosition;
}
// Start idle hover animation
if (enableIdleHover && _context.Animator != null)
{
_idleHoverTween = _context.Animator.StartIdleHover(idleHoverHeight, idleHoverDuration);
}
}
public void OnPointerEnter(PointerEventData eventData)
{
// Scale up slightly on hover
if (_context.Animator != null)
{
_context.Animator.AnimateScale(Vector3.one * hoverScaleMultiplier, 0.2f);
}
}
public void OnPointerExit(PointerEventData eventData)
{
// Scale back to normal
if (_context.Animator != null)
{
_context.Animator.AnimateScale(Vector3.one, 0.2f);
}
}
public void OnPointerClick(PointerEventData eventData)
{
// Click to flip - transition to flipping state
_context.StateMachine.ChangeState("FlippingState");
}
private void OnDisable()
{
// Stop idle hover animation when leaving state
if (_idleHoverTween != null)
{
_idleHoverTween.Stop();
_idleHoverTween = null;
// Return to original position
RectTransform rectTransform = _context.RootTransform.GetComponent<RectTransform>();
if (rectTransform != null && _context.Animator != null)
{
_context.Animator.AnimateAnchoredPosition(_originalPosition, 0.3f);
}
}
// Reset scale
if (_context.Animator != null)
{
_context.Animator.AnimateScale(Vector3.one, 0.2f);
}
// Hide card back when leaving state
if (cardBackVisual != null)
{
cardBackVisual.SetActive(false);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7da1bdc06be348f2979d3b92cc7ce723
timeCreated: 1762884650

View File

@@ -0,0 +1,65 @@
using UnityEngine;
using UnityEngine.EventSystems;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Optional helper component for handling drag/drop integration with existing DragDrop system.
/// Can be attached to Card root to bridge between state machine and drag system.
/// </summary>
public class CardInteractionHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
private CardContext _context;
private CardDraggingState _draggingState;
private bool _isDragging;
private void Awake()
{
_context = GetComponent<CardContext>();
}
public void OnBeginDrag(PointerEventData eventData)
{
// Only allow drag from certain states
var currentState = _context.StateMachine.currentState?.name;
if (currentState != "RevealedState" && currentState != "PlacedInSlotState")
{
return;
}
// Transition to dragging state
_context.StateMachine.ChangeState("DraggingState");
_draggingState = _context.StateMachine.currentState?.GetComponent<CardDraggingState>();
_isDragging = true;
}
public void OnDrag(PointerEventData eventData)
{
if (!_isDragging || _draggingState == null) return;
// Update drag position
Vector3 worldPosition;
RectTransformUtility.ScreenPointToWorldPointInRectangle(
transform as RectTransform,
eventData.position,
eventData.pressEventCamera,
out worldPosition
);
_draggingState.UpdateDragPosition(worldPosition);
}
public void OnEndDrag(PointerEventData eventData)
{
if (!_isDragging || _draggingState == null) return;
_isDragging = false;
// Check if dropped over a valid slot
// This would integrate with your existing AlbumCardSlot system
// For now, just return to revealed state
_draggingState.OnDroppedOutsideSlot();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 860a5494378b465a9cc05b2b3d585bf9
timeCreated: 1762884900

View File

@@ -0,0 +1,53 @@
using Core;
using Core.SaveLoad;
using UnityEngine.EventSystems;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Placed in slot state - card is in an album slot and can be clicked to enlarge.
/// Manages the parent slot reference.
/// </summary>
public class CardPlacedInSlotState : AppleState, IPointerClickHandler
{
private CardContext _context;
private AlbumCardSlot _parentSlot;
private void Awake()
{
_context = GetComponentInParent<CardContext>();
}
public override void OnEnterState()
{
Logging.Debug($"[CardPlacedInSlotState] Card placed in slot: {_context.CardData?.Name}");
// Card is now part of the album, no special visuals needed
// Just wait for interaction
}
/// <summary>
/// Set the parent slot this card belongs to
/// </summary>
public void SetParentSlot(AlbumCardSlot slot)
{
_parentSlot = slot;
}
/// <summary>
/// Get the parent slot
/// </summary>
public AlbumCardSlot GetParentSlot()
{
return _parentSlot;
}
public void OnPointerClick(PointerEventData eventData)
{
// Click to enlarge when in album
Logging.Debug($"[CardPlacedInSlotState] Card clicked in slot, transitioning to enlarged state");
_context.StateMachine.ChangeState("AlbumEnlargedState");
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 11a4dc9bbeed4623baf1675ab5679bd9
timeCreated: 1762884899

View File

@@ -0,0 +1,33 @@
using Core.SaveLoad;
using UnityEngine;
using UnityEngine.EventSystems;
namespace UI.CardSystem.StateMachine.States
{
/// <summary>
/// Revealed state - card is flipped and visible, waiting for interaction.
/// Can be clicked to enlarge or dragged to place in album.
/// </summary>
public class CardRevealedState : AppleState, IPointerClickHandler
{
private CardContext _context;
private void Awake()
{
_context = GetComponentInParent<CardContext>();
}
public override void OnEnterState()
{
// Card is simply visible and interactable
// No special animations needed
}
public void OnPointerClick(PointerEventData eventData)
{
// Click to enlarge
_context.StateMachine.ChangeState("EnlargedNewState");
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 891aad90d6cc41869e497f94d1408859
timeCreated: 1762884650