- **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
173 lines
5.7 KiB
C#
173 lines
5.7 KiB
C#
using System.Collections.Generic;
|
|
using AppleHills.Data.CardSystem;
|
|
using Core;
|
|
using UnityEngine;
|
|
|
|
namespace UI.CardSystem
|
|
{
|
|
/// <summary>
|
|
/// Manages album page navigation, zone mapping, and page flip tracking.
|
|
/// Created and owned by AlbumViewPage (not a Unity component).
|
|
/// </summary>
|
|
public class AlbumNavigationService
|
|
{
|
|
private readonly BookCurlPro.BookPro _book;
|
|
private readonly BookTabButton[] _zoneTabs;
|
|
|
|
private bool _isPageFlipping = false;
|
|
|
|
/// <summary>
|
|
/// Is the book currently flipping to a page?
|
|
/// </summary>
|
|
public bool IsPageFlipping => _isPageFlipping;
|
|
|
|
/// <summary>
|
|
/// Constructor - called by AlbumViewPage's lazy property
|
|
/// </summary>
|
|
public AlbumNavigationService(BookCurlPro.BookPro book, BookTabButton[] zoneTabs)
|
|
{
|
|
_book = book;
|
|
_zoneTabs = zoneTabs;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if we're currently viewing the album proper (not the menu page)
|
|
/// </summary>
|
|
public bool IsInAlbumProper()
|
|
{
|
|
if (_book == null)
|
|
{
|
|
Logging.Warning("[AlbumNavigationService] Book reference is null");
|
|
return false;
|
|
}
|
|
|
|
// Page 1 is the menu/cover, page 2+ are album pages with card slots
|
|
return _book.CurrentPaper > 1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Navigate to the page where a specific card belongs
|
|
/// </summary>
|
|
public void NavigateToCardPage(CardData cardData, System.Action onComplete)
|
|
{
|
|
if (cardData == null || _book == null)
|
|
{
|
|
onComplete?.Invoke();
|
|
return;
|
|
}
|
|
|
|
// Find target page based on card's zone
|
|
int targetPage = FindPageForZone(cardData.Zone);
|
|
|
|
if (targetPage < 0)
|
|
{
|
|
Logging.Warning($"[AlbumNavigationService] No page found for zone {cardData.Zone}");
|
|
onComplete?.Invoke();
|
|
return;
|
|
}
|
|
|
|
// Mark as flipping
|
|
_isPageFlipping = true;
|
|
Logging.Debug($"[AlbumNavigationService] Starting page flip to page {targetPage}");
|
|
|
|
// Get or add AutoFlip component
|
|
BookCurlPro.AutoFlip autoFlip = _book.GetComponent<BookCurlPro.AutoFlip>();
|
|
if (autoFlip == null)
|
|
{
|
|
autoFlip = _book.gameObject.AddComponent<BookCurlPro.AutoFlip>();
|
|
}
|
|
|
|
// Start flipping with callback
|
|
autoFlip.enabled = true;
|
|
autoFlip.StartFlipping(targetPage, () =>
|
|
{
|
|
// Mark as complete
|
|
_isPageFlipping = false;
|
|
Logging.Debug($"[AlbumNavigationService] Page flip to {targetPage} completed");
|
|
|
|
// Call original callback if provided
|
|
onComplete?.Invoke();
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get list of card definition IDs on the current page
|
|
/// </summary>
|
|
public List<string> GetDefinitionsOnCurrentPage()
|
|
{
|
|
var result = new List<string>();
|
|
if (_book == null) return result;
|
|
|
|
int currentPage = _book.CurrentPaper;
|
|
|
|
// Find all AlbumCardSlot in scene
|
|
var allSlots = Object.FindObjectsByType<AlbumCardSlot>(FindObjectsSortMode.None);
|
|
|
|
foreach (var slot in allSlots)
|
|
{
|
|
if (IsSlotOnPage(slot.transform, currentPage))
|
|
{
|
|
if (slot.TargetCardDefinition != null && !string.IsNullOrEmpty(slot.TargetCardDefinition.Id))
|
|
{
|
|
result.Add(slot.TargetCardDefinition.Id);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
#region Private Helpers
|
|
|
|
/// <summary>
|
|
/// Find the target page for a card zone using BookTabButtons
|
|
/// </summary>
|
|
private int FindPageForZone(CardZone zone)
|
|
{
|
|
if (_zoneTabs == null || _zoneTabs.Length == 0)
|
|
{
|
|
Logging.Warning("[AlbumNavigationService] No zone tabs available!");
|
|
return -1;
|
|
}
|
|
|
|
foreach (var tab in _zoneTabs)
|
|
{
|
|
if (tab.Zone == zone)
|
|
{
|
|
return tab.TargetPage;
|
|
}
|
|
}
|
|
|
|
Logging.Warning($"[AlbumNavigationService] No BookTabButton found for zone {zone}");
|
|
return -1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if a slot's transform is on a specific book page
|
|
/// </summary>
|
|
private bool IsSlotOnPage(Transform slotTransform, int pageIndex)
|
|
{
|
|
if (_book == null || _book.papers == null || pageIndex < 0 || pageIndex >= _book.papers.Length)
|
|
return false;
|
|
|
|
var paper = _book.papers[pageIndex];
|
|
if (paper == null) return false;
|
|
|
|
// Check if slotTransform parent hierarchy contains paper.Front or paper.Back
|
|
Transform current = slotTransform;
|
|
while (current != null)
|
|
{
|
|
if ((paper.Front != null && current.gameObject == paper.Front) ||
|
|
(paper.Back != null && current.gameObject == paper.Back))
|
|
return true;
|
|
current = current.parent;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
|