Merge a card refresh (#59)
- **Refactored Card Placement Flow** - Separated card presentation from orchestration logic - Extracted `CornerCardManager` for pending card lifecycle (spawn, shuffle, rebuild) - Extracted `AlbumNavigationService` for book page navigation and zone mapping - Extracted `CardEnlargeController` for backdrop management and card reparenting - Implemented controller pattern (non-MonoBehaviour) for complex logic - Cards now unparent from slots before rebuild to prevent premature destruction - **Improved Corner Card Display** - Fixed cards spawning on top of each other during rebuild - Implemented shuffle-to-front logic (remaining cards occupy slots 0→1→2) - Added smart card selection (prioritizes cards matching current album page) - Pending cards now removed from queue immediately on drag start - Corner cards rebuild after each placement with proper slot reassignment - **Enhanced Album Card Viewing** - Added dramatic scale increase when viewing cards from album slots - Implemented shrink animation when dismissing enlarged cards - Cards transition: `PlacedInSlotState` → `AlbumEnlargedState` → `PlacedInSlotState` - Backdrop shows/hides with card enlarge/shrink cycle - Cards reparent to enlarged container while viewing, return to slot after - **State Machine Improvements** - Added `CardStateNames` constants for type-safe state transitions - Implemented `ICardClickHandler` and `ICardStateDragHandler` interfaces - State transitions now use cached property indices - `BoosterCardContext` separated from `CardContext` for single responsibility - **Code Cleanup** - Identified unused `SlotContainerHelper.cs` (superseded by `CornerCardManager`) - Identified unused `BoosterPackDraggable.canOpenOnDrop` field - Identified unused `AlbumViewPage._previousInputMode` (hardcoded value) - Identified unused `Card.OnPlacedInAlbumSlot` event (no subscribers) Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: #59
This commit is contained in:
@@ -169,6 +169,7 @@ namespace Core
|
||||
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
|
||||
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous<InteractionSettings>();
|
||||
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous<DivingMinigameSettings>();
|
||||
var cardSystemSettings = SettingsProvider.Instance.LoadSettingsSynchronous<CardSystemSettings>();
|
||||
|
||||
// Register settings with service locator
|
||||
if (playerSettings != null)
|
||||
@@ -200,9 +201,19 @@ namespace Core
|
||||
{
|
||||
Debug.LogError("Failed to load MinigameSettings");
|
||||
}
|
||||
|
||||
if (cardSystemSettings != null)
|
||||
{
|
||||
ServiceLocator.Register<ICardSystemSettings>(cardSystemSettings);
|
||||
Logging.Debug("CardSystemSettings registered successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to load CardSystemSettings");
|
||||
}
|
||||
|
||||
// Log success
|
||||
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
|
||||
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null && cardSystemSettings != null;
|
||||
if (_settingsLoaded)
|
||||
{
|
||||
Logging.Debug("All settings loaded and registered with ServiceLocator");
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Core.SaveLoad
|
||||
private void Start()
|
||||
{
|
||||
// Direct registration - SaveLoadManager guaranteed available (priority 25)
|
||||
if (SaveLoadManager.Instance != null)
|
||||
if (SaveLoadManager.Instance != null && ShouldParticipateInSave())
|
||||
{
|
||||
SaveLoadManager.Instance.RegisterParticipant(this);
|
||||
}
|
||||
@@ -126,6 +126,15 @@ namespace Core.SaveLoad
|
||||
// Match ManagedBehaviour convention: SceneName/GameObjectName/ComponentType
|
||||
return $"{sceneName}/{gameObject.name}/AppleMachine";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true to participate in save/load system.
|
||||
/// Override this in derived classes to opt out (return false).
|
||||
/// </summary>
|
||||
public virtual bool ShouldParticipateInSave()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetSceneName()
|
||||
{
|
||||
|
||||
@@ -29,6 +29,13 @@
|
||||
/// Used to prevent double-restoration when inactive objects become active.
|
||||
/// </summary>
|
||||
bool HasBeenRestored { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this participant wants to participate in save/load system.
|
||||
/// Return false to opt out (participant will not be saved or restored).
|
||||
/// Useful for transient objects like UI elements that don't need persistence.
|
||||
/// </summary>
|
||||
bool ShouldParticipateInSave();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +130,13 @@ namespace Core.SaveLoad
|
||||
participants[saveId] = participant;
|
||||
Logging.Debug($"[SaveLoadManager] Registered participant: {saveId}");
|
||||
|
||||
// Skip restoration for participants that opt out
|
||||
if (!participant.ShouldParticipateInSave())
|
||||
{
|
||||
Logging.Debug($"[SaveLoadManager] Participant opted out of save/load: {saveId}");
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have save data loaded and the participant hasn't been restored yet
|
||||
if (IsSaveDataLoaded && currentSaveData != null && !participant.HasBeenRestored)
|
||||
{
|
||||
@@ -446,6 +453,13 @@ namespace Core.SaveLoad
|
||||
{
|
||||
string saveId = kvp.Key;
|
||||
ISaveParticipant participant = kvp.Value;
|
||||
|
||||
// Skip participants that opt out of save system
|
||||
if (!participant.ShouldParticipateInSave())
|
||||
{
|
||||
Logging.Debug($"[SaveLoadManager] Skipping participant (opted out): {saveId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -630,6 +644,13 @@ namespace Core.SaveLoad
|
||||
{
|
||||
string saveId = kvp.Key;
|
||||
ISaveParticipant participant = kvp.Value;
|
||||
|
||||
// Skip participants that opt out of save system
|
||||
if (!participant.ShouldParticipateInSave())
|
||||
{
|
||||
Logging.Debug($"[SaveLoadManager] Skipping participant (opted out): {saveId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
102
Assets/Scripts/Core/Settings/CardSystemSettings.cs
Normal file
102
Assets/Scripts/Core/Settings/CardSystemSettings.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppleHills.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings for the card system - controls animations, interactions, and progression
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "CardSystemSettings", menuName = "AppleHills/Settings/Card System", order = 4)]
|
||||
public class CardSystemSettings : BaseSettings, ICardSystemSettings
|
||||
{
|
||||
[Header("Idle Hover Animations")]
|
||||
[Tooltip("Height of the idle hover animation in pixels")]
|
||||
[SerializeField] private float idleHoverHeight = 10f;
|
||||
|
||||
[Tooltip("Duration of one complete hover cycle in seconds")]
|
||||
[SerializeField] private float idleHoverDuration = 1.5f;
|
||||
|
||||
[Tooltip("Scale multiplier when hovering over a card (1.05 = 5% larger)")]
|
||||
[SerializeField] private float hoverScaleMultiplier = 1.05f;
|
||||
|
||||
[Header("Flip Animations")]
|
||||
[Tooltip("Duration of the card flip animation in seconds")]
|
||||
[SerializeField] private float flipDuration = 0.6f;
|
||||
|
||||
[Tooltip("Scale punch amount during flip (1.1 = 10% larger at peak)")]
|
||||
[SerializeField] private float flipScalePunch = 1.1f;
|
||||
|
||||
[Header("Enlarge/Shrink Animations")]
|
||||
[Tooltip("Scale for new cards when enlarged (1.5 = 150% of normal size)")]
|
||||
[SerializeField] private float newCardEnlargedScale = 1.5f;
|
||||
|
||||
[Tooltip("Scale for album cards when enlarged (4.0 = 400% of normal size - dramatic showcase)")]
|
||||
[SerializeField] private float albumCardEnlargedScale = 4.0f;
|
||||
|
||||
[Tooltip("Duration of scale animations in seconds")]
|
||||
[SerializeField] private float scaleDuration = 0.3f;
|
||||
|
||||
[Header("Drag & Drop")]
|
||||
[Tooltip("Scale multiplier when dragging a card (1.1 = 10% larger)")]
|
||||
[SerializeField] private float dragScale = 1.1f;
|
||||
|
||||
[Header("Progression System")]
|
||||
[Tooltip("Number of duplicate cards needed to upgrade rarity")]
|
||||
[SerializeField] private int cardsToUpgrade = 5;
|
||||
|
||||
[Header("General Animation")]
|
||||
[Tooltip("Default animation duration when not specified in seconds")]
|
||||
[SerializeField] private float defaultAnimationDuration = 0.3f;
|
||||
|
||||
// ICardSystemSettings implementation - Idle Hover Animations
|
||||
public float IdleHoverHeight => idleHoverHeight;
|
||||
public float IdleHoverDuration => idleHoverDuration;
|
||||
public float HoverScaleMultiplier => hoverScaleMultiplier;
|
||||
|
||||
// ICardSystemSettings implementation - Flip Animations
|
||||
public float FlipDuration => flipDuration;
|
||||
public float FlipScalePunch => flipScalePunch;
|
||||
|
||||
// ICardSystemSettings implementation - Enlarge/Shrink Animations
|
||||
public float NewCardEnlargedScale => newCardEnlargedScale;
|
||||
public float AlbumCardEnlargedScale => albumCardEnlargedScale;
|
||||
public float ScaleDuration => scaleDuration;
|
||||
|
||||
// ICardSystemSettings implementation - Drag & Drop
|
||||
public float DragScale => dragScale;
|
||||
|
||||
// ICardSystemSettings implementation - Progression System
|
||||
public int CardsToUpgrade => cardsToUpgrade;
|
||||
|
||||
// ICardSystemSettings implementation - General Animation
|
||||
public float DefaultAnimationDuration => defaultAnimationDuration;
|
||||
|
||||
public override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
|
||||
// Validate idle hover animations
|
||||
idleHoverHeight = Mathf.Max(0f, idleHoverHeight);
|
||||
idleHoverDuration = Mathf.Max(0.1f, idleHoverDuration);
|
||||
hoverScaleMultiplier = Mathf.Max(1.0f, hoverScaleMultiplier);
|
||||
|
||||
// Validate flip animations
|
||||
flipDuration = Mathf.Max(0.1f, flipDuration);
|
||||
flipScalePunch = Mathf.Max(1.0f, flipScalePunch);
|
||||
|
||||
// Validate enlarge/shrink animations
|
||||
newCardEnlargedScale = Mathf.Max(1.0f, newCardEnlargedScale);
|
||||
albumCardEnlargedScale = Mathf.Max(1.0f, albumCardEnlargedScale);
|
||||
scaleDuration = Mathf.Max(0.1f, scaleDuration);
|
||||
|
||||
// Validate drag & drop
|
||||
dragScale = Mathf.Max(1.0f, dragScale);
|
||||
|
||||
// Validate progression system
|
||||
cardsToUpgrade = Mathf.Max(1, cardsToUpgrade);
|
||||
|
||||
// Validate general animation
|
||||
defaultAnimationDuration = Mathf.Max(0.1f, defaultAnimationDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
Assets/Scripts/Core/Settings/CardSystemSettings.cs.meta
Normal file
3
Assets/Scripts/Core/Settings/CardSystemSettings.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce6f8e26f4e74a9ab16c190529e67638
|
||||
timeCreated: 1762934668
|
||||
@@ -128,9 +128,36 @@ namespace AppleHills.Core.Settings
|
||||
float[] ViewfinderProgressThresholds { get; }
|
||||
float PaddingFactor { get; }
|
||||
float MaxSizePercent { get; }
|
||||
float MinSizePercent { get; }
|
||||
public float MinSizePercent { get; }
|
||||
public PhotoInputModes PhotoInputMode { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for card system settings
|
||||
/// </summary>
|
||||
public interface ICardSystemSettings
|
||||
{
|
||||
// Idle Hover Animations
|
||||
float IdleHoverHeight { get; }
|
||||
float IdleHoverDuration { get; }
|
||||
float HoverScaleMultiplier { get; }
|
||||
|
||||
// Photo Input Settings
|
||||
PhotoInputModes PhotoInputMode { get; }
|
||||
// Flip Animations
|
||||
float FlipDuration { get; }
|
||||
float FlipScalePunch { get; }
|
||||
|
||||
// Enlarge/Shrink Animations
|
||||
float NewCardEnlargedScale { get; }
|
||||
float AlbumCardEnlargedScale { get; }
|
||||
float ScaleDuration { get; }
|
||||
|
||||
// Drag & Drop
|
||||
float DragScale { get; }
|
||||
|
||||
// Progression System
|
||||
int CardsToUpgrade { get; }
|
||||
|
||||
// General Animation
|
||||
float DefaultAnimationDuration { get; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user