192 lines
6.1 KiB
C#
192 lines
6.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using AppleHills.Data.CardSystem;
|
|
using Data.CardSystem;
|
|
using UI.DragAndDrop.Core;
|
|
using UnityEngine;
|
|
|
|
namespace UI.CardSystem
|
|
{
|
|
/// <summary>
|
|
/// Draggable card for album reveal system.
|
|
/// Handles both tap and drag-hold interactions for revealing cards.
|
|
/// Auto-snaps to matching album slot on release/tap.
|
|
/// </summary>
|
|
public class AlbumCardDraggable : DraggableObject
|
|
{
|
|
[Header("Album Card Settings")]
|
|
[SerializeField] private FlippableCard flippableCard;
|
|
[SerializeField] private float holdRevealDelay = 0.1f;
|
|
|
|
private CardData _cardData;
|
|
private bool _isRevealed = false;
|
|
private bool _isDragRevealing = false;
|
|
private bool _waitingForPlacementTap = false;
|
|
private Coroutine _holdRevealCoroutine;
|
|
private bool _isHolding = false; // Track if pointer is currently down
|
|
|
|
// Events
|
|
public event Action<AlbumCardDraggable, CardData> OnCardRevealed;
|
|
public event Action<AlbumCardDraggable, CardData> OnCardPlacedInAlbum;
|
|
|
|
public CardData CardData => _cardData;
|
|
public bool IsRevealed => _isRevealed;
|
|
public CardZone Zone => _cardData?.Zone ?? CardZone.AppleHills;
|
|
|
|
protected override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
// Auto-find FlippableCard if not assigned
|
|
if (flippableCard == null)
|
|
{
|
|
flippableCard = GetComponent<FlippableCard>();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setup the card data (stores it but doesn't reveal until tapped/dragged)
|
|
/// </summary>
|
|
public void SetupCard(CardData data)
|
|
{
|
|
_cardData = data;
|
|
|
|
if (flippableCard != null)
|
|
{
|
|
flippableCard.SetupCard(data);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reveal the card (flip to show front)
|
|
/// </summary>
|
|
public void RevealCard()
|
|
{
|
|
if (_isRevealed) return;
|
|
|
|
_isRevealed = true;
|
|
|
|
if (flippableCard != null)
|
|
{
|
|
flippableCard.FlipToReveal();
|
|
}
|
|
|
|
OnCardRevealed?.Invoke(this, _cardData);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Snap to the matching album slot
|
|
/// </summary>
|
|
public void SnapToAlbumSlot()
|
|
{
|
|
if (_cardData == null)
|
|
{
|
|
Debug.LogWarning("[AlbumCardDraggable] Cannot snap to slot - no card data assigned.");
|
|
return;
|
|
}
|
|
|
|
// Find all album card slots in the scene
|
|
AlbumCardSlot[] allSlots = FindObjectsByType<AlbumCardSlot>(FindObjectsSortMode.None);
|
|
|
|
AlbumCardSlot matchingSlot = null;
|
|
foreach (var slot in allSlots)
|
|
{
|
|
if (slot.CanAcceptCard(_cardData))
|
|
{
|
|
matchingSlot = slot;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (matchingSlot != null)
|
|
{
|
|
// Assign to slot with animation
|
|
AssignToSlot(matchingSlot, true);
|
|
|
|
// Mark slot as permanently occupied
|
|
matchingSlot.OnCardPlaced();
|
|
|
|
// Disable dragging - card is now static in album
|
|
SetDraggingEnabled(false);
|
|
|
|
// Notify that card was placed
|
|
// Note: Card already moved from pending to inventory in OnCardRevealed
|
|
OnCardPlacedInAlbum?.Invoke(this, _cardData);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"[AlbumCardDraggable] Could not find matching slot for card '{_cardData.Name}' (Zone: {_cardData.Zone}, Index: {_cardData.CollectionIndex})");
|
|
}
|
|
}
|
|
|
|
protected override void OnPointerDownHook()
|
|
{
|
|
base.OnPointerDownHook();
|
|
|
|
_isHolding = true;
|
|
|
|
// Start hold-reveal timer if card not yet revealed
|
|
if (!_isRevealed && _holdRevealCoroutine == null)
|
|
{
|
|
_holdRevealCoroutine = StartCoroutine(HoldRevealTimer());
|
|
}
|
|
}
|
|
|
|
protected override void OnPointerUpHook(bool longPress)
|
|
{
|
|
base.OnPointerUpHook(longPress);
|
|
|
|
_isHolding = false;
|
|
|
|
// Cancel hold timer if running
|
|
if (_holdRevealCoroutine != null)
|
|
{
|
|
StopCoroutine(_holdRevealCoroutine);
|
|
_holdRevealCoroutine = null;
|
|
}
|
|
|
|
// Handle tap (not dragged)
|
|
if (!_wasDragged)
|
|
{
|
|
if (!_isRevealed)
|
|
{
|
|
// First tap: reveal the card
|
|
RevealCard();
|
|
_waitingForPlacementTap = true;
|
|
}
|
|
else if (_waitingForPlacementTap)
|
|
{
|
|
// Second tap: snap to slot
|
|
_waitingForPlacementTap = false;
|
|
SnapToAlbumSlot();
|
|
}
|
|
}
|
|
else if (_isDragRevealing)
|
|
{
|
|
// Was drag-revealed, auto-snap on release
|
|
_isDragRevealing = false;
|
|
SnapToAlbumSlot();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Coroutine to reveal card after holding for specified duration
|
|
/// </summary>
|
|
private IEnumerator HoldRevealTimer()
|
|
{
|
|
yield return new WaitForSeconds(holdRevealDelay);
|
|
|
|
// If still holding after delay, reveal the card
|
|
if (!_isRevealed && _isHolding)
|
|
{
|
|
RevealCard();
|
|
_isDragRevealing = true;
|
|
Debug.Log("[AlbumCardDraggable] Card revealed via hold");
|
|
}
|
|
|
|
_holdRevealCoroutine = null;
|
|
}
|
|
}
|
|
}
|
|
|