- **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
111 lines
3.9 KiB
C#
111 lines
3.9 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace BookCurlPro
|
|
{
|
|
[RequireComponent(typeof(BookPro))]
|
|
public class AutoFlip : MonoBehaviour
|
|
{
|
|
public BookPro ControledBook;
|
|
public FlipMode Mode;
|
|
public float PageFlipTime = 1;
|
|
public float DelayBeforeStart;
|
|
public float TimeBetweenPages = 5;
|
|
public bool AutoStartFlip = true;
|
|
|
|
[Header("Events")]
|
|
public UnityEvent OnTargetReached;
|
|
|
|
bool flippingStarted = false;
|
|
bool isPageFlipping = false;
|
|
float elapsedTime = 0;
|
|
float nextPageCountDown = 0;
|
|
bool isBookInteractable;
|
|
// Use this for initialization
|
|
void Start()
|
|
{
|
|
if (!ControledBook)
|
|
ControledBook = GetComponent<BookPro>();
|
|
|
|
if (AutoStartFlip)
|
|
StartFlipping(ControledBook.EndFlippingPaper + 1);
|
|
}
|
|
public void FlipRightPage()
|
|
{
|
|
if (isPageFlipping) return;
|
|
if (ControledBook.CurrentPaper >= ControledBook.papers.Length) return;
|
|
isPageFlipping = true;
|
|
PageFlipper.FlipPage(ControledBook, PageFlipTime, FlipMode.RightToLeft, () => { isPageFlipping = false; });
|
|
}
|
|
public void FlipLeftPage()
|
|
{
|
|
if (isPageFlipping) return;
|
|
if (ControledBook.CurrentPaper <= 0) return;
|
|
isPageFlipping = true;
|
|
PageFlipper.FlipPage(ControledBook, PageFlipTime, FlipMode.LeftToRight, () => { isPageFlipping = false; });
|
|
}
|
|
int targetPaper;
|
|
|
|
/// <summary>
|
|
/// Start flipping to target page with optional completion callback
|
|
/// </summary>
|
|
public void StartFlipping(int target, UnityAction callback)
|
|
{
|
|
if (callback != null)
|
|
{
|
|
if (OnTargetReached == null)
|
|
OnTargetReached = new UnityEvent();
|
|
|
|
OnTargetReached.RemoveAllListeners();
|
|
OnTargetReached.AddListener(callback);
|
|
}
|
|
|
|
StartFlipping(target);
|
|
}
|
|
|
|
public void StartFlipping(int target)
|
|
{
|
|
isBookInteractable = ControledBook.interactable;
|
|
ControledBook.interactable = false;
|
|
flippingStarted = true;
|
|
elapsedTime = 0;
|
|
nextPageCountDown = 0;
|
|
targetPaper = target;
|
|
if (target > ControledBook.CurrentPaper) Mode = FlipMode.RightToLeft;
|
|
else if (target < ControledBook.currentPaper) Mode = FlipMode.LeftToRight;
|
|
}
|
|
void Update()
|
|
{
|
|
if (flippingStarted)
|
|
{
|
|
elapsedTime += Time.deltaTime;
|
|
if (elapsedTime > DelayBeforeStart)
|
|
{
|
|
if (nextPageCountDown < 0)
|
|
{
|
|
if ((ControledBook.CurrentPaper < targetPaper &&
|
|
Mode == FlipMode.RightToLeft) ||
|
|
(ControledBook.CurrentPaper > targetPaper &&
|
|
Mode == FlipMode.LeftToRight))
|
|
{
|
|
isPageFlipping = true;
|
|
PageFlipper.FlipPage(ControledBook, PageFlipTime, Mode, () => { isPageFlipping = false; });
|
|
}
|
|
else
|
|
{
|
|
flippingStarted = false;
|
|
ControledBook.interactable = isBookInteractable;
|
|
this.enabled = false;
|
|
|
|
// Invoke target reached event
|
|
OnTargetReached?.Invoke();
|
|
}
|
|
|
|
nextPageCountDown = PageFlipTime + TimeBetweenPages + Time.deltaTime;
|
|
}
|
|
nextPageCountDown -= Time.deltaTime;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |