Files
AppleHillsProduction/Assets/Scripts/UI/CardSystem/StateMachine/Card.cs

212 lines
7.6 KiB
C#
Raw Normal View History

2025-11-11 20:25:23 +01:00
using AppleHills.Data.CardSystem;
2025-11-12 14:39:38 +01:00
using Core;
2025-11-11 20:25:23 +01:00
using Core.SaveLoad;
2025-11-12 14:39:38 +01:00
using UI.DragAndDrop.Core;
2025-11-11 20:25:23 +01:00
using UnityEngine;
namespace UI.CardSystem.StateMachine
{
2025-11-17 14:30:07 +01:00
// ...existing code...
2025-11-12 14:39:38 +01:00
public class Card : DraggableObject
2025-11-11 20:25:23 +01:00
{
[Header("Components")]
[SerializeField] private CardContext context;
[SerializeField] private CardAnimator animator;
[SerializeField] private AppleMachine stateMachine;
[Header("Configuration")]
[SerializeField] private string initialState = "IdleState";
// Public accessors
public CardContext Context => context;
public CardAnimator Animator => animator;
public AppleMachine StateMachine => stateMachine;
public CardData CardData => context?.CardData;
2025-11-16 20:35:54 +01:00
// State inspection properties for booster flow
public bool IsIdle => GetCurrentStateName() == "IdleState";
public bool IsRevealing => !IsIdle && !IsComplete;
public bool IsComplete => context?.HasCompletedReveal ?? false;
// Event fired when this card is successfully placed into an AlbumCardSlot
public event System.Action<Card, AlbumCardSlot> OnPlacedInAlbumSlot;
2025-11-12 14:39:38 +01:00
protected override void Initialize()
2025-11-11 20:25:23 +01:00
{
2025-11-12 14:39:38 +01:00
base.Initialize(); // Call DraggableObject initialization
2025-11-11 20:25:23 +01:00
// Auto-find components if not assigned
if (context == null)
context = GetComponent<CardContext>();
if (animator == null)
animator = GetComponent<CardAnimator>();
if (stateMachine == null)
stateMachine = GetComponentInChildren<AppleMachine>();
}
2025-11-12 14:39:38 +01:00
#region DraggableObject Hooks - Trigger State Transitions
protected override void OnDragStartedHook()
{
base.OnDragStartedHook();
2025-11-17 10:59:59 +01:00
2025-11-17 14:30:07 +01:00
// Always emit the generic drag started event for external consumers (AlbumViewPage, etc.)
2025-11-17 10:59:59 +01:00
context?.NotifyDragStarted();
2025-11-17 14:30:07 +01:00
// Check if current state wants to handle drag behavior
if (stateMachine?.currentState != null)
2025-11-17 08:39:41 +01:00
{
2025-11-17 14:30:07 +01:00
var dragHandler = stateMachine.currentState.GetComponent<ICardStateDragHandler>();
if (dragHandler != null && dragHandler.OnCardDragStarted(context))
2025-11-17 08:39:41 +01:00
{
2025-11-17 14:30:07 +01:00
return; // State handled it, don't do default behavior
2025-11-17 08:39:41 +01:00
}
}
2025-11-17 14:30:07 +01:00
// Default behavior: transition to DraggingState
Logging.Debug($"[Card] Drag started on {CardData?.Name}, transitioning to DraggingState");
ChangeState("DraggingState");
2025-11-12 14:39:38 +01:00
}
protected override void OnDragEndedHook()
{
base.OnDragEndedHook();
2025-11-17 14:30:07 +01:00
// Always emit the generic drag ended event for external consumers
context?.NotifyDragEnded();
// Check if current state wants to handle drag end
if (stateMachine?.currentState != null)
{
var dragHandler = stateMachine.currentState.GetComponent<ICardStateDragHandler>();
if (dragHandler != null && dragHandler.OnCardDragEnded(context))
{
return; // State handled it
}
}
// Default behavior for states that don't implement custom drag end
2025-11-17 08:39:41 +01:00
string current = GetCurrentStateName();
if (current == "DraggingState")
2025-11-12 14:39:38 +01:00
{
2025-11-17 08:39:41 +01:00
if (CurrentSlot is AlbumCardSlot albumSlot)
{
Logging.Debug($"[Card] Dropped in album slot, transitioning to PlacedInSlotState");
var placedState = GetStateComponent<States.CardPlacedInSlotState>("PlacedInSlotState");
if (placedState != null)
{
placedState.SetParentSlot(albumSlot);
}
ChangeState("PlacedInSlotState");
OnPlacedInAlbumSlot?.Invoke(this, albumSlot);
}
else
2025-11-12 14:39:38 +01:00
{
2025-11-17 08:39:41 +01:00
Logging.Debug("[Card] Dropped outside valid slot, returning to RevealedState");
ChangeState("RevealedState");
2025-11-12 14:39:38 +01:00
}
}
}
#endregion
2025-11-11 20:25:23 +01:00
/// <summary>
/// Setup the card with data and optional initial state
/// </summary>
2025-11-16 20:35:54 +01:00
public void SetupCard(CardData data, string startState = null)
2025-11-11 20:25:23 +01:00
{
if (context != null)
{
2025-11-16 20:35:54 +01:00
context.SetupCard(data);
2025-11-11 20:25:23 +01:00
}
// Start the state machine with specified or default state
string targetState = startState ?? initialState;
if (stateMachine != null && !string.IsNullOrEmpty(targetState))
{
stateMachine.ChangeState(targetState);
}
}
/// <summary>
/// Setup for booster reveal flow (starts at IdleState, will flip on click)
2025-11-12 14:39:38 +01:00
/// Dragging is DISABLED for booster cards
2025-11-16 20:35:54 +01:00
/// States will query CardSystemManager for collection state as needed
2025-11-11 20:25:23 +01:00
/// </summary>
public void SetupForBoosterReveal(CardData data, bool isNew)
{
2025-11-16 20:35:54 +01:00
SetupCard(data, "IdleState");
2025-11-12 14:39:38 +01:00
SetDraggingEnabled(false); // Booster cards cannot be dragged
}
2025-11-11 20:25:23 +01:00
/// <summary>
/// Setup for album placement (starts at PlacedInSlotState)
2025-11-12 14:39:38 +01:00
/// Dragging is DISABLED once placed in slot
2025-11-11 20:25:23 +01:00
/// </summary>
public void SetupForAlbumSlot(CardData data, AlbumCardSlot slot)
{
2025-11-16 20:35:54 +01:00
SetupCard(data, "PlacedInSlotState");
2025-11-12 14:39:38 +01:00
SetDraggingEnabled(false); // Cards in slots cannot be dragged out
2025-11-11 20:25:23 +01:00
// Set the parent slot on the PlacedInSlotState
var placedState = GetStateComponent<States.CardPlacedInSlotState>("PlacedInSlotState");
if (placedState != null)
{
placedState.SetParentSlot(slot);
}
}
2025-11-17 08:39:41 +01:00
/// <summary>
/// Setup for album pending state (starts at PendingFaceDownState)
/// Dragging is ENABLED; state will assign data when dragged
/// </summary>
public void SetupForAlbumPending()
{
// Start with no data; state will assign when dragged
SetupCard(null, "PendingFaceDownState");
SetDraggingEnabled(true);
}
2025-11-11 20:25:23 +01:00
/// <summary>
/// Transition to a specific state
/// </summary>
public void ChangeState(string stateName)
{
if (stateMachine != null)
{
stateMachine.ChangeState(stateName);
}
}
/// <summary>
/// Get a specific state component by name
/// </summary>
public T GetStateComponent<T>(string stateName) where T : AppleState
{
if (stateMachine == null) return null;
Transform stateTransform = stateMachine.transform.Find(stateName);
if (stateTransform != null)
{
return stateTransform.GetComponent<T>();
}
return null;
}
/// <summary>
/// Get the current active state name
/// </summary>
public string GetCurrentStateName()
{
if (stateMachine?.currentState != null)
{
return stateMachine.currentState.name;
}
return "None";
}
}
}