Update the card kerfufle
This commit is contained in:
3
Assets/Scripts/UI/CardSystem/StateMachine.meta
Normal file
3
Assets/Scripts/UI/CardSystem/StateMachine.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80f8dd01edcd4742b3edbb5c7fcecd12
|
||||
timeCreated: 1762884650
|
||||
122
Assets/Scripts/UI/CardSystem/StateMachine/Card.cs
Normal file
122
Assets/Scripts/UI/CardSystem/StateMachine/Card.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using AppleHills.Data.CardSystem;
|
||||
using Core.SaveLoad;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI.CardSystem.StateMachine
|
||||
{
|
||||
/// <summary>
|
||||
/// Main Card controller component.
|
||||
/// Orchestrates the card state machine, context, and animator.
|
||||
/// This is the single entry point for working with cards.
|
||||
/// </summary>
|
||||
public class Card : MonoBehaviour
|
||||
{
|
||||
[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;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Auto-find components if not assigned
|
||||
if (context == null)
|
||||
context = GetComponent<CardContext>();
|
||||
|
||||
if (animator == null)
|
||||
animator = GetComponent<CardAnimator>();
|
||||
|
||||
if (stateMachine == null)
|
||||
stateMachine = GetComponentInChildren<AppleMachine>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup the card with data and optional initial state
|
||||
/// </summary>
|
||||
public void SetupCard(CardData data, bool isNew = false, string startState = null)
|
||||
{
|
||||
if (context != null)
|
||||
{
|
||||
context.SetupCard(data, isNew);
|
||||
}
|
||||
|
||||
// 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)
|
||||
/// </summary>
|
||||
public void SetupForBoosterReveal(CardData data, bool isNew)
|
||||
{
|
||||
SetupCard(data, isNew, "IdleState");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup for album placement (starts at PlacedInSlotState)
|
||||
/// </summary>
|
||||
public void SetupForAlbumSlot(CardData data, AlbumCardSlot slot)
|
||||
{
|
||||
SetupCard(data, false, "PlacedInSlotState");
|
||||
|
||||
// Set the parent slot on the PlacedInSlotState
|
||||
var placedState = GetStateComponent<States.CardPlacedInSlotState>("PlacedInSlotState");
|
||||
if (placedState != null)
|
||||
{
|
||||
placedState.SetParentSlot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
Assets/Scripts/UI/CardSystem/StateMachine/Card.cs.meta
Normal file
3
Assets/Scripts/UI/CardSystem/StateMachine/Card.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d97dd4e4bc3246e9bed5ac227f13de10
|
||||
timeCreated: 1762884900
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ddd745ae12984de9974292d201c89d9c
|
||||
timeCreated: 1762884650
|
||||
359
Assets/Scripts/UI/CardSystem/StateMachine/CardAnimator.cs
Normal file
359
Assets/Scripts/UI/CardSystem/StateMachine/CardAnimator.cs
Normal file
@@ -0,0 +1,359 @@
|
||||
using Pixelplacement;
|
||||
using Pixelplacement.TweenSystem;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace UI.CardSystem.StateMachine
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles common card animations that can be reused across states.
|
||||
/// Centralizes animation logic to avoid duplication.
|
||||
/// Animates the CARD ROOT TRANSFORM (all states follow the card).
|
||||
/// </summary>
|
||||
public class CardAnimator : MonoBehaviour
|
||||
{
|
||||
[Header("Animation Settings")]
|
||||
[SerializeField] private float defaultDuration = 0.3f;
|
||||
|
||||
private Transform _transform;
|
||||
private RectTransform _rectTransform;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_transform = transform;
|
||||
_rectTransform = GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
#region Scale Animations
|
||||
|
||||
/// <summary>
|
||||
/// Animate scale to target value
|
||||
/// </summary>
|
||||
public TweenBase AnimateScale(Vector3 targetScale, float? duration = null, Action onComplete = null)
|
||||
{
|
||||
return Tween.LocalScale(_transform, targetScale, duration ?? defaultDuration, 0f,
|
||||
Tween.EaseInOut, completeCallback: onComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pulse scale animation (scale up then back to normal)
|
||||
/// </summary>
|
||||
public void PulseScale(float pulseAmount = 1.1f, float duration = 0.2f, Action onComplete = null)
|
||||
{
|
||||
Vector3 originalScale = _transform.localScale;
|
||||
Vector3 pulseScale = originalScale * pulseAmount;
|
||||
|
||||
Tween.LocalScale(_transform, pulseScale, duration, 0f, Tween.EaseOutBack,
|
||||
completeCallback: () =>
|
||||
{
|
||||
Tween.LocalScale(_transform, originalScale, duration, 0f, Tween.EaseInBack,
|
||||
completeCallback: onComplete);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pop-in animation (scale from 0 to 1 with overshoot)
|
||||
/// </summary>
|
||||
public TweenBase PopIn(float duration = 0.5f, Action onComplete = null)
|
||||
{
|
||||
_transform.localScale = Vector3.zero;
|
||||
return Tween.LocalScale(_transform, Vector3.one, duration, 0f,
|
||||
Tween.EaseOutBack, completeCallback: onComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pop-out animation (scale from current to 0)
|
||||
/// </summary>
|
||||
public TweenBase PopOut(float duration = 0.3f, Action onComplete = null)
|
||||
{
|
||||
return Tween.LocalScale(_transform, Vector3.zero, duration, 0f,
|
||||
Tween.EaseInBack, completeCallback: onComplete);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Position Animations (RectTransform)
|
||||
|
||||
/// <summary>
|
||||
/// Animate anchored position (for UI elements)
|
||||
/// </summary>
|
||||
public TweenBase AnimateAnchoredPosition(Vector2 targetPosition, float? duration = null, Action onComplete = null)
|
||||
{
|
||||
if (_rectTransform == null)
|
||||
{
|
||||
Debug.LogWarning("CardAnimator: No RectTransform found for anchored position animation");
|
||||
return null;
|
||||
}
|
||||
|
||||
return Tween.AnchoredPosition(_rectTransform, targetPosition, duration ?? defaultDuration, 0f,
|
||||
Tween.EaseInOut, completeCallback: onComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Animate local position
|
||||
/// </summary>
|
||||
public TweenBase AnimateLocalPosition(Vector3 targetPosition, float? duration = null, Action onComplete = null)
|
||||
{
|
||||
return Tween.LocalPosition(_transform, targetPosition, duration ?? defaultDuration, 0f,
|
||||
Tween.EaseInOut, completeCallback: onComplete);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rotation Animations
|
||||
|
||||
/// <summary>
|
||||
/// Animate local rotation to target
|
||||
/// </summary>
|
||||
public TweenBase AnimateLocalRotation(Quaternion targetRotation, float? duration = null, Action onComplete = null)
|
||||
{
|
||||
return Tween.LocalRotation(_transform, targetRotation, duration ?? defaultDuration, 0f,
|
||||
Tween.EaseInOut, completeCallback: onComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotate a child object (typically used by states for CardBackVisual, etc.)
|
||||
/// </summary>
|
||||
public TweenBase AnimateChildRotation(Transform childTransform, Quaternion targetRotation,
|
||||
float duration, Action onComplete = null)
|
||||
{
|
||||
return Tween.LocalRotation(childTransform, targetRotation, duration, 0f,
|
||||
Tween.EaseInOut, completeCallback: onComplete);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Flip Animations
|
||||
|
||||
/// <summary>
|
||||
/// Play card flip animation - rotates card back from 0° to 90°, then card front from 180° to 0°
|
||||
/// Based on FlippableCard.FlipToReveal()
|
||||
/// </summary>
|
||||
public void PlayFlip(Transform cardBack, Transform cardFront, float duration = 0.6f, Action onComplete = null)
|
||||
{
|
||||
// Phase 1: Rotate both to 90 degrees (edge view)
|
||||
if (cardBack != null)
|
||||
{
|
||||
Tween.LocalRotation(cardBack, Quaternion.Euler(0, 90, 0), duration * 0.5f, 0f, Tween.EaseInOut);
|
||||
}
|
||||
|
||||
if (cardFront != null)
|
||||
{
|
||||
Tween.LocalRotation(cardFront, Quaternion.Euler(0, 90, 0), duration * 0.5f, 0f, Tween.EaseInOut,
|
||||
completeCallback: () =>
|
||||
{
|
||||
// At edge (90°), switch visibility
|
||||
if (cardBack != null)
|
||||
cardBack.gameObject.SetActive(false);
|
||||
if (cardFront != null)
|
||||
cardFront.gameObject.SetActive(true);
|
||||
|
||||
// Phase 2: Rotate front from 90 to 0 (show at correct orientation)
|
||||
Tween.LocalRotation(cardFront, Quaternion.Euler(0, 0, 0), duration * 0.5f, 0f, Tween.EaseInOut,
|
||||
completeCallback: onComplete);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play scale punch during flip animation for extra juice
|
||||
/// Based on FlippableCard.FlipToReveal()
|
||||
/// </summary>
|
||||
public void PlayFlipScalePunch(float punchScale = 1.1f, float duration = 0.6f)
|
||||
{
|
||||
Vector3 originalScale = _transform.localScale;
|
||||
|
||||
Tween.LocalScale(_transform, originalScale * punchScale, duration * 0.5f, 0f, Tween.EaseOutBack,
|
||||
completeCallback: () =>
|
||||
{
|
||||
Tween.LocalScale(_transform, originalScale, duration * 0.5f, 0f, Tween.EaseInBack);
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enlarge/Shrink Animations
|
||||
|
||||
/// <summary>
|
||||
/// Enlarge card to specified scale
|
||||
/// Based on FlippableCard.EnlargeCard() and AlbumCard.EnlargeCard()
|
||||
/// </summary>
|
||||
public void PlayEnlarge(float targetScale = 2.5f, float duration = 0.3f, Action onComplete = null)
|
||||
{
|
||||
Tween.LocalScale(_transform, Vector3.one * targetScale, duration, 0f, Tween.EaseOutBack,
|
||||
completeCallback: onComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shrink card back to original scale
|
||||
/// Based on AlbumCard.ShrinkCard() and FlippableCard.ReturnToNormalSize()
|
||||
/// </summary>
|
||||
public void PlayShrink(Vector3 targetScale, float duration = 0.3f, Action onComplete = null)
|
||||
{
|
||||
Tween.LocalScale(_transform, targetScale, duration, 0f, Tween.EaseInBack,
|
||||
completeCallback: onComplete);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Combined Animations
|
||||
|
||||
/// <summary>
|
||||
/// Hover enter animation (lift and scale)
|
||||
/// For RectTransform UI elements
|
||||
/// </summary>
|
||||
public void HoverEnter(float liftAmount = 20f, float scaleMultiplier = 1.05f,
|
||||
float duration = 0.2f, Action onComplete = null)
|
||||
{
|
||||
if (_rectTransform != null)
|
||||
{
|
||||
Vector2 currentPos = _rectTransform.anchoredPosition;
|
||||
Vector2 targetPos = currentPos + Vector2.up * liftAmount;
|
||||
|
||||
Tween.AnchoredPosition(_rectTransform, targetPos, duration, 0f, Tween.EaseOutBack);
|
||||
Tween.LocalScale(_transform, Vector3.one * scaleMultiplier, duration, 0f,
|
||||
Tween.EaseOutBack, completeCallback: onComplete);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback for non-RectTransform
|
||||
Vector3 currentPos = _transform.localPosition;
|
||||
Vector3 targetPos = currentPos + Vector3.up * liftAmount;
|
||||
|
||||
Tween.LocalPosition(_transform, targetPos, duration, 0f, Tween.EaseOutBack);
|
||||
Tween.LocalScale(_transform, Vector3.one * scaleMultiplier, duration, 0f,
|
||||
Tween.EaseOutBack, completeCallback: onComplete);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hover exit animation (return to original position and scale)
|
||||
/// </summary>
|
||||
public void HoverExit(Vector2 originalPosition, float duration = 0.2f, Action onComplete = null)
|
||||
{
|
||||
if (_rectTransform != null)
|
||||
{
|
||||
Tween.AnchoredPosition(_rectTransform, originalPosition, duration, 0f, Tween.EaseInBack);
|
||||
Tween.LocalScale(_transform, Vector3.one, duration, 0f,
|
||||
Tween.EaseInBack, completeCallback: onComplete);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tween.LocalPosition(_transform, originalPosition, duration, 0f, Tween.EaseInBack);
|
||||
Tween.LocalScale(_transform, Vector3.one, duration, 0f,
|
||||
Tween.EaseInBack, completeCallback: onComplete);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Idle hover animation (gentle bobbing loop)
|
||||
/// Returns the TweenBase so caller can stop it later
|
||||
/// </summary>
|
||||
public TweenBase StartIdleHover(float hoverHeight = 10f, float duration = 1.5f)
|
||||
{
|
||||
if (_rectTransform != null)
|
||||
{
|
||||
Vector2 originalPos = _rectTransform.anchoredPosition;
|
||||
Vector2 targetPos = originalPos + Vector2.up * hoverHeight;
|
||||
|
||||
return Tween.Value(0f, 1f,
|
||||
(val) =>
|
||||
{
|
||||
if (_rectTransform != null)
|
||||
{
|
||||
float t = Mathf.Sin(val * Mathf.PI * 2f) * 0.5f + 0.5f;
|
||||
_rectTransform.anchoredPosition = Vector2.Lerp(originalPos, targetPos, t);
|
||||
}
|
||||
},
|
||||
duration, 0f, Tween.EaseInOut, Tween.LoopType.Loop);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Flip Animations (Two-Phase)
|
||||
|
||||
/// <summary>
|
||||
/// Flip animation: Phase 1 - Rotate card back to edge (0° to 90°)
|
||||
/// Used by FlippingState to hide the back
|
||||
/// </summary>
|
||||
public void FlipPhase1_HideBack(Transform cardBackTransform, float duration, Action onHalfwayComplete)
|
||||
{
|
||||
Tween.LocalRotation(cardBackTransform, Quaternion.Euler(0, 90, 0), duration, 0f,
|
||||
Tween.EaseInOut, completeCallback: onHalfwayComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flip animation: Phase 2 - Rotate card front from back to face (180° to 90° to 0°)
|
||||
/// Used by FlippingState to reveal the front
|
||||
/// </summary>
|
||||
public void FlipPhase2_RevealFront(Transform cardFrontTransform, float duration, Action onComplete)
|
||||
{
|
||||
// First rotate from 180 to 90 (edge)
|
||||
Tween.LocalRotation(cardFrontTransform, Quaternion.Euler(0, 90, 0), duration, 0f,
|
||||
Tween.EaseInOut,
|
||||
completeCallback: () =>
|
||||
{
|
||||
// Then rotate from 90 to 0 (face)
|
||||
Tween.LocalRotation(cardFrontTransform, Quaternion.Euler(0, 0, 0), duration, 0f,
|
||||
Tween.EaseInOut, completeCallback: onComplete);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale punch during flip (makes flip more juicy)
|
||||
/// </summary>
|
||||
public void FlipScalePunch(float punchMultiplier = 1.1f, float totalDuration = 0.6f)
|
||||
{
|
||||
Vector3 originalScale = _transform.localScale;
|
||||
Vector3 punchScale = originalScale * punchMultiplier;
|
||||
|
||||
Tween.LocalScale(_transform, punchScale, totalDuration * 0.5f, 0f, Tween.EaseOutBack,
|
||||
completeCallback: () =>
|
||||
{
|
||||
Tween.LocalScale(_transform, originalScale, totalDuration * 0.5f, 0f, Tween.EaseInBack);
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utility
|
||||
|
||||
/// <summary>
|
||||
/// Stop all active tweens on this transform
|
||||
/// </summary>
|
||||
public void StopAllAnimations()
|
||||
{
|
||||
Tween.Stop(_transform.GetInstanceID());
|
||||
if (_rectTransform != null)
|
||||
Tween.Stop(_rectTransform.GetInstanceID());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset transform to default values
|
||||
/// </summary>
|
||||
public void ResetTransform()
|
||||
{
|
||||
StopAllAnimations();
|
||||
_transform.localPosition = Vector3.zero;
|
||||
_transform.localRotation = Quaternion.identity;
|
||||
_transform.localScale = Vector3.one;
|
||||
|
||||
if (_rectTransform != null)
|
||||
_rectTransform.anchoredPosition = Vector2.zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get current anchored position (useful for saving before hover)
|
||||
/// </summary>
|
||||
public Vector2 GetAnchoredPosition()
|
||||
{
|
||||
return _rectTransform != null ? _rectTransform.anchoredPosition : Vector2.zero;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5eacab725f4346d091696042b9cd2a82
|
||||
timeCreated: 1762887143
|
||||
66
Assets/Scripts/UI/CardSystem/StateMachine/CardContext.cs
Normal file
66
Assets/Scripts/UI/CardSystem/StateMachine/CardContext.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
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;
|
||||
|
||||
// Public accessors
|
||||
public CardDisplay CardDisplay => cardDisplay;
|
||||
public CardAnimator Animator => cardAnimator;
|
||||
public AppleMachine StateMachine => stateMachine;
|
||||
public Transform RootTransform => transform;
|
||||
public CardData CardData => cardData;
|
||||
|
||||
// Runtime state
|
||||
public bool IsNewCard { get; set; }
|
||||
public int RepeatCardCount { get; set; }
|
||||
|
||||
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>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup the card with data
|
||||
/// </summary>
|
||||
public void SetupCard(CardData data, bool isNew = false, int repeatCount = 0)
|
||||
{
|
||||
cardData = data;
|
||||
IsNewCard = isNew;
|
||||
RepeatCardCount = repeatCount;
|
||||
|
||||
if (cardDisplay != null)
|
||||
{
|
||||
cardDisplay.SetupCard(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the card display component
|
||||
/// </summary>
|
||||
public CardDisplay GetCardDisplay() => cardDisplay;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b3126aaaa66448fa3d5bd772aaf5784
|
||||
timeCreated: 1762884650
|
||||
3
Assets/Scripts/UI/CardSystem/StateMachine/States.meta
Normal file
3
Assets/Scripts/UI/CardSystem/StateMachine/States.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43f3b0a00e934598a6a58abad11930a4
|
||||
timeCreated: 1762884650
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f33526d9bb8458d8dc5ba41a88561da
|
||||
timeCreated: 1762884900
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b17e4e1d7139446c9c4e0a813067331c
|
||||
timeCreated: 1762884899
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 698741a53f314b598af359a81d914ed3
|
||||
timeCreated: 1762884651
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 257f0c81caa14481812a8ca0397bf567
|
||||
timeCreated: 1762884651
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7223d6cab8d94f74b00a6a538291850a
|
||||
timeCreated: 1762884650
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7da1bdc06be348f2979d3b92cc7ce723
|
||||
timeCreated: 1762884650
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 860a5494378b465a9cc05b2b3d585bf9
|
||||
timeCreated: 1762884900
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11a4dc9bbeed4623baf1675ab5679bd9
|
||||
timeCreated: 1762884899
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 891aad90d6cc41869e497f94d1408859
|
||||
timeCreated: 1762884650
|
||||
Reference in New Issue
Block a user