Files
AppleHillsProduction/Assets/Scripts/UI/CardSystem/StateMachine/CardContext.cs
2025-11-17 23:38:34 +01:00

191 lines
6.6 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using AppleHills.Data.CardSystem;
using Core.SaveLoad;
using UnityEngine;
namespace UI.CardSystem.StateMachine
{
/// <summary>
/// Shared context for card states.
/// Provides access to common components and data that states need.
/// </summary>
public class CardContext : MonoBehaviour
{
[Header("Core Components")]
[SerializeField] private CardDisplay cardDisplay;
[SerializeField] private CardAnimator cardAnimator;
private AppleMachine stateMachine;
[Header("Card Data")]
private CardData cardData;
// Cached reference to AlbumViewPage (lazy-loaded)
private AlbumViewPage _albumViewPage;
// Public accessors
public CardDisplay CardDisplay => cardDisplay;
public CardAnimator Animator => cardAnimator;
public AppleMachine StateMachine => stateMachine;
public Transform RootTransform => transform;
public CardData CardData => cardData;
/// <summary>
/// Get the AlbumViewPage instance (cached to avoid repeated FindFirstObjectByType calls)
/// </summary>
public AlbumViewPage AlbumViewPage
{
get
{
if (_albumViewPage == null)
{
_albumViewPage = FindFirstObjectByType<AlbumViewPage>();
}
return _albumViewPage;
}
}
// Runtime state
public bool IsClickable { get; set; } = true;
// TODO: Move to booster-specific states - this is workflow-specific, not generic context
public bool SuppressRevealBadges { get; set; } = false; // Set by states to suppress NEW/REPEAT badges in revealed state
// Original transform data (captured on spawn for shrink animations)
public Vector3 OriginalScale { get; private set; }
public Vector3 OriginalPosition { get; private set; }
public Quaternion OriginalRotation { get; private set; }
// TODO: Move to BoosterOpeningPage - reveal flow is booster-specific workflow coordination
// Single event for reveal flow completion
public event Action<CardContext> OnRevealFlowComplete;
// Generic drag event - fired when drag starts, consumers decide how to handle based on current state
public event Action<CardContext> OnDragStarted;
// Generic drag end event - fired when drag ends, consumers decide how to handle based on current state
public event Action<CardContext> OnDragEnded;
// TODO: Move to booster-specific states - this tracks reveal workflow completion
private bool _hasCompletedReveal = false;
public bool HasCompletedReveal => _hasCompletedReveal;
// TODO: Move to booster-specific states - workflow coordination method
// Helper method for states to signal completion
public void NotifyRevealComplete()
{
if (!_hasCompletedReveal)
{
_hasCompletedReveal = true;
OnRevealFlowComplete?.Invoke(this);
}
}
// Helper method for states/card to signal drag started
public void NotifyDragStarted()
{
OnDragStarted?.Invoke(this);
}
// Helper method for states/card to signal drag ended
public void NotifyDragEnded()
{
OnDragEnded?.Invoke(this);
}
private void Awake()
{
// Auto-find components if not assigned
if (cardDisplay == null)
cardDisplay = GetComponentInChildren<CardDisplay>();
if (cardAnimator == null)
cardAnimator = GetComponent<CardAnimator>();
if (stateMachine == null)
stateMachine = GetComponentInChildren<AppleMachine>();
}
private void OnEnable()
{
// Subscribe to CardDisplay click and route to active state
if (cardDisplay != null)
{
cardDisplay.OnCardClicked += HandleCardDisplayClicked;
}
}
private void OnDisable()
{
if (cardDisplay != null)
{
cardDisplay.OnCardClicked -= HandleCardDisplayClicked;
}
}
private void HandleCardDisplayClicked(CardDisplay _)
{
// Gate by clickability
if (!IsClickable) return;
if (stateMachine == null || stateMachine.currentState == null) return;
var handler = stateMachine.currentState.GetComponent<ICardClickHandler>();
if (handler != null)
{
handler.OnCardClicked(this);
}
}
/// <summary>
/// Setup the card with data
/// </summary>
public void SetupCard(CardData data)
{
cardData = data;
_hasCompletedReveal = false; // Reset completion flag
// Capture original transform for shrink animations.
// If current scale is ~0 (pop-in staging), default to Vector3.one.
var currentScale = transform.localScale;
if (currentScale.x < 0.01f && currentScale.y < 0.01f && currentScale.z < 0.01f)
{
OriginalScale = Vector3.one;
}
else
{
OriginalScale = currentScale;
}
OriginalPosition = transform.localPosition;
OriginalRotation = transform.localRotation;
if (cardDisplay != null)
{
cardDisplay.SetupCard(data);
}
}
/// <summary>
/// Update card data without re-capturing original transform values.
/// Use this when assigning data to an already-initialized card (e.g., pending cards on drag).
/// This prevents changing OriginalScale when the card is already correctly sized.
/// </summary>
public void UpdateCardData(CardData data)
{
cardData = data;
_hasCompletedReveal = false; // Reset completion flag
// Don't re-capture OriginalScale/Position/Rotation
// This preserves the transform values captured during initial setup
if (cardDisplay != null)
{
cardDisplay.SetupCard(data);
}
}
/// <summary>
/// Get the card display component
/// </summary>
public CardDisplay GetCardDisplay() => cardDisplay;
}
}