From 2fb77e1040f30f2f053720b94b713374ae0925b5 Mon Sep 17 00:00:00 2001 From: Michal Adam Pikulski Date: Tue, 21 Oct 2025 12:10:16 +0200 Subject: [PATCH] Cleanup the card implementation, add some readme files and update namespaces --- .junie/guidelines.md | 12 + Assets/Editor/CardSystem/CardEditorWindow.cs | 2 +- Assets/Scripts/Tests/CardSystemTester.cs | 2 +- Assets/Scripts/UI/CardSystem/AlbumViewPage.cs | 3 +- .../UI/CardSystem/BoosterNotificationDot.cs | 8 +- .../UI/CardSystem/BoosterOpeningPage.cs | 4 +- Assets/Scripts/UI/CardSystem/CardAlbumUI.cs | 7 +- Assets/Scripts/UI/CardSystem/CardMenuPage.cs | 8 +- Assets/Scripts/UI/CardSystem/CardUIElement.cs | 9 +- Assets/Scripts/UI/Core.meta | 3 + .../Scripts/UI/{CardSystem => Core}/UIPage.cs | 2 +- .../UI/{CardSystem => Core}/UIPage.cs.meta | 0 .../{CardSystem => Core}/UIPageController.cs | 2 +- .../UIPageController.cs.meta | 0 ...card_system_implementation_plan_updated.md | 114 ------ docs/card_system_integration_and_testing.md | 159 -------- docs/card_system_playbook.md | 340 ++++++++++++++++++ docs/card_system_ui_setup_guide_updated.md | 309 ---------------- docs/ui_page_navigation.md | 194 ++++++++++ 19 files changed, 570 insertions(+), 608 deletions(-) create mode 100644 .junie/guidelines.md create mode 100644 Assets/Scripts/UI/Core.meta rename Assets/Scripts/UI/{CardSystem => Core}/UIPage.cs (98%) rename Assets/Scripts/UI/{CardSystem => Core}/UIPage.cs.meta (100%) rename Assets/Scripts/UI/{CardSystem => Core}/UIPageController.cs (99%) rename Assets/Scripts/UI/{CardSystem => Core}/UIPageController.cs.meta (100%) delete mode 100644 docs/card_system_implementation_plan_updated.md delete mode 100644 docs/card_system_integration_and_testing.md create mode 100644 docs/card_system_playbook.md delete mode 100644 docs/card_system_ui_setup_guide_updated.md create mode 100644 docs/ui_page_navigation.md diff --git a/.junie/guidelines.md b/.junie/guidelines.md new file mode 100644 index 00000000..e8e0891c --- /dev/null +++ b/.junie/guidelines.md @@ -0,0 +1,12 @@ +# Project Guidelines + +This is a placeholder of the project guidelines for Junie. +Replace this text with any project-level instructions for Junie, e.g.: + +* What is the project structure +* Whether Junie should run tests to check the correctness of the proposed solution +* How does Junie run tests (once it requires any non-standard approach) +* Whether Junie should build the project before submitting the result +* Any code-style related instructions + +As an option you can ask Junie to create these guidelines for you. diff --git a/Assets/Editor/CardSystem/CardEditorWindow.cs b/Assets/Editor/CardSystem/CardEditorWindow.cs index 5e7b0618..fa912f1c 100644 --- a/Assets/Editor/CardSystem/CardEditorWindow.cs +++ b/Assets/Editor/CardSystem/CardEditorWindow.cs @@ -2,12 +2,12 @@ using System.IO; using System.Linq; using AppleHills.Data.CardSystem; -using AppleHills.UI.CardSystem; using UnityEditor; using UnityEditor.AddressableAssets.Settings; using UnityEngine; using UnityEngine.UI; using AppleHills.Editor.Utilities; +using UI.CardSystem; namespace AppleHills.Editor.CardSystem { diff --git a/Assets/Scripts/Tests/CardSystemTester.cs b/Assets/Scripts/Tests/CardSystemTester.cs index 236777cc..fbcdc89b 100644 --- a/Assets/Scripts/Tests/CardSystemTester.cs +++ b/Assets/Scripts/Tests/CardSystemTester.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using UnityEditor; using Data.CardSystem; using Core; -using AppleHills.UI.CardSystem; +using UI.CardSystem; using UnityEngine.UI; namespace AppleHills.Tests diff --git a/Assets/Scripts/UI/CardSystem/AlbumViewPage.cs b/Assets/Scripts/UI/CardSystem/AlbumViewPage.cs index 2626902c..f325c744 100644 --- a/Assets/Scripts/UI/CardSystem/AlbumViewPage.cs +++ b/Assets/Scripts/UI/CardSystem/AlbumViewPage.cs @@ -4,10 +4,11 @@ using Core; using Data.CardSystem; using Pixelplacement; using TMPro; +using UI.Core; using UnityEngine; using UnityEngine.UI; -namespace AppleHills.UI.CardSystem +namespace UI.CardSystem { /// /// UI page for viewing the player's card collection in an album. diff --git a/Assets/Scripts/UI/CardSystem/BoosterNotificationDot.cs b/Assets/Scripts/UI/CardSystem/BoosterNotificationDot.cs index f1740c37..81a1142c 100644 --- a/Assets/Scripts/UI/CardSystem/BoosterNotificationDot.cs +++ b/Assets/Scripts/UI/CardSystem/BoosterNotificationDot.cs @@ -1,9 +1,9 @@ -using UnityEngine; -using TMPro; -using Pixelplacement; +using Pixelplacement; using Pixelplacement.TweenSystem; +using TMPro; +using UnityEngine; -namespace AppleHills.UI.CardSystem +namespace UI.CardSystem { /// /// Manages a notification dot that displays a count (e.g., booster packs) diff --git a/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs b/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs index ab61fb57..09b5a892 100644 --- a/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs +++ b/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs @@ -4,11 +4,11 @@ using AppleHills.Data.CardSystem; using Core; using Data.CardSystem; using Pixelplacement; -using TMPro; +using UI.Core; using UnityEngine; using UnityEngine.UI; -namespace AppleHills.UI.CardSystem +namespace UI.CardSystem { /// /// UI page for opening booster packs and displaying the cards obtained. diff --git a/Assets/Scripts/UI/CardSystem/CardAlbumUI.cs b/Assets/Scripts/UI/CardSystem/CardAlbumUI.cs index 48637933..77fb7674 100644 --- a/Assets/Scripts/UI/CardSystem/CardAlbumUI.cs +++ b/Assets/Scripts/UI/CardSystem/CardAlbumUI.cs @@ -1,13 +1,12 @@ -using System; -using System.Collections; -using AppleHills.Data.CardSystem; +using AppleHills.Data.CardSystem; using Core; using Data.CardSystem; using Pixelplacement; +using UI.Core; using UnityEngine; using UnityEngine.UI; -namespace AppleHills.UI.CardSystem +namespace UI.CardSystem { /// /// Main UI controller for the card album system. diff --git a/Assets/Scripts/UI/CardSystem/CardMenuPage.cs b/Assets/Scripts/UI/CardSystem/CardMenuPage.cs index d6475db0..7b9edaa8 100644 --- a/Assets/Scripts/UI/CardSystem/CardMenuPage.cs +++ b/Assets/Scripts/UI/CardSystem/CardMenuPage.cs @@ -1,13 +1,11 @@ -using System.Collections.Generic; -using AppleHills.Data.CardSystem; -using Core; +using Core; using Data.CardSystem; using Pixelplacement; -using TMPro; +using UI.Core; using UnityEngine; using UnityEngine.UI; -namespace AppleHills.UI.CardSystem +namespace UI.CardSystem { /// /// UI page for the main menu of the card system. diff --git a/Assets/Scripts/UI/CardSystem/CardUIElement.cs b/Assets/Scripts/UI/CardSystem/CardUIElement.cs index 8884e810..5de15881 100644 --- a/Assets/Scripts/UI/CardSystem/CardUIElement.cs +++ b/Assets/Scripts/UI/CardSystem/CardUIElement.cs @@ -1,15 +1,12 @@ using System; -using System.Collections.Generic; using AppleHills.Data.CardSystem; using Core; -using UnityEngine; using TMPro; -using UnityEngine.UI; -#if UNITY_EDITOR using UnityEditor; -#endif +using UnityEngine; +using UnityEngine.UI; -namespace AppleHills.UI.CardSystem +namespace UI.CardSystem { /// /// Handles displaying and interacting with a single card in the UI. diff --git a/Assets/Scripts/UI/Core.meta b/Assets/Scripts/UI/Core.meta new file mode 100644 index 00000000..78f8f7c8 --- /dev/null +++ b/Assets/Scripts/UI/Core.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ea8964f9870d45479f09a4b05c2b0d0c +timeCreated: 1761040697 \ No newline at end of file diff --git a/Assets/Scripts/UI/CardSystem/UIPage.cs b/Assets/Scripts/UI/Core/UIPage.cs similarity index 98% rename from Assets/Scripts/UI/CardSystem/UIPage.cs rename to Assets/Scripts/UI/Core/UIPage.cs index dc5bc60d..e72555b1 100644 --- a/Assets/Scripts/UI/CardSystem/UIPage.cs +++ b/Assets/Scripts/UI/Core/UIPage.cs @@ -1,7 +1,7 @@ using System; using UnityEngine; -namespace AppleHills.UI.CardSystem +namespace UI.Core { /// /// Base class for UI pages that can transition in and out. diff --git a/Assets/Scripts/UI/CardSystem/UIPage.cs.meta b/Assets/Scripts/UI/Core/UIPage.cs.meta similarity index 100% rename from Assets/Scripts/UI/CardSystem/UIPage.cs.meta rename to Assets/Scripts/UI/Core/UIPage.cs.meta diff --git a/Assets/Scripts/UI/CardSystem/UIPageController.cs b/Assets/Scripts/UI/Core/UIPageController.cs similarity index 99% rename from Assets/Scripts/UI/CardSystem/UIPageController.cs rename to Assets/Scripts/UI/Core/UIPageController.cs index 83da5797..492dd7b9 100644 --- a/Assets/Scripts/UI/CardSystem/UIPageController.cs +++ b/Assets/Scripts/UI/Core/UIPageController.cs @@ -5,7 +5,7 @@ using Core; using UnityEngine; using UnityEngine.InputSystem; -namespace AppleHills.UI.CardSystem +namespace UI.Core { /// /// Manages UI page transitions and maintains a stack of active pages. diff --git a/Assets/Scripts/UI/CardSystem/UIPageController.cs.meta b/Assets/Scripts/UI/Core/UIPageController.cs.meta similarity index 100% rename from Assets/Scripts/UI/CardSystem/UIPageController.cs.meta rename to Assets/Scripts/UI/Core/UIPageController.cs.meta diff --git a/docs/card_system_implementation_plan_updated.md b/docs/card_system_implementation_plan_updated.md deleted file mode 100644 index 487c3cd7..00000000 --- a/docs/card_system_implementation_plan_updated.md +++ /dev/null @@ -1,114 +0,0 @@ -# Card System Implementation Plan - -## Current Implementation Analysis - -### Data Layer - -1. **CardData.cs**: - - Represents an instance of a card in the player's collection - - Contains unique ID, rarity, and copies owned - - Has a reference to its CardDefinition for display information - - Includes methods for rarity upgrades when collecting duplicates - - Well-structured with proper serialization support - -2. **CardDefinition.cs**: - - ScriptableObject template for creating card instances - - Contains basic info (name, description), visuals, and collection data - - Provides helper methods like CreateCardData() and GetBackgroundColor() - - Supports different zones (AppleHills, Quarry, Forest, Mountain, Beach) - -3. **CardSystemManager.cs**: - - Singleton manager for the card system - - Manages available card definitions and player inventory - - Includes event callbacks for booster packs and card collection - - Implements functionality for adding and opening booster packs - -4. **CardInventory.cs**: - - Fully implemented management of the player's card collection - - Includes methods for adding cards and tracking booster packs - - Provides filtering methods for different card types - - Supports card lookup by various properties (zone, rarity) - -5. **CardVisualConfig.cs**: - - ScriptableObject for configuring the visual appearance of cards - - Maps rarities to colors and zones to colors/shapes - - Uses dictionary lookups for efficient access - -### UI Layer - -1. **CardUIElement.cs**: - - Handles displaying a single card in the UI - - Updates visuals based on card data (rarity, zone) - - References UI elements like card name text, images, frames, etc. - -2. **UIPageController.cs**: - - Manages UI page transitions with a stack-based navigation system - - Provides methods for pushing, popping, and clearing the page stack - - Uses events to notify when pages change - -3. **UI Page Components**: - - **CardMenuPage.cs**: Main menu for card system navigation - - **AlbumViewPage.cs**: Simplified implementation that shows filtered cards in grid - - **BoosterOpeningPage.cs**: Interactive card reveal experience - - **CardAlbumUI.cs**: Main controller for the card system UI - - **UIPage.cs**: Base class for common page functionality - -## Implementation Status - -### Completed -1. **Complete CardInventory Implementation**: - - Full implementation with methods to manage the player's card collection - - Filtering, sorting, and organization features - - Integration with CardSystemManager - -2. **Booster Pack Generation**: - - Logic to generate random booster packs with appropriate rarity distribution - - Methods for awarding booster packs to the player - - Events for notifying UI when booster packs are obtained - -3. **Card Collection UI**: - - Simplified album browsing UI with filtering and sorting options - - Removed unnecessary card stack and slot system - - Updated AlbumViewPage to use TextMeshPro components - -4. **Booster Pack Opening UI (In Progress)**: - - Implemented interactive card reveal system - - Added card back prefabs for clickable reveal experience - - Created flip animations and particle effects for card reveals - - Updated to support revealing three cards individually - -### Still Needed -1. **Booster Opening UI Refinement**: - - Fine-tune animation timings and transitions - - Implement custom card back designs - - Add more visual/audio feedback for different rarities - -2. **Save/Load System**: - - Implement persistence for the player's card collection - - Add autosave functionality for cards and booster packs - -3. **Card Collection Statistics**: - - Add UI for tracking collection completion - - Implement achievements for collecting sets - -## Next Steps - -### 1. Complete the Booster Opening Experience -- Create proper card back prefab with appropriate design -- Test and refine the card reveal animations -- Ensure particle effects and sounds play correctly - -### 2. Add Save/Load System -- Implement JSON serialization for CardInventory -- Add autosave triggers after obtaining new cards -- Create save/load methods in CardSystemManager - -### 3. Polish the Overall Experience -- Add transition animations between pages -- Improve visual feedback for obtaining new cards -- Implement collection statistics display - -### 4. Additional Features (Optional) -- Special collection bonuses for completing sets -- Card trading system with NPCs -- Card usage mechanics beyond collection diff --git a/docs/card_system_integration_and_testing.md b/docs/card_system_integration_and_testing.md deleted file mode 100644 index 6d27d832..00000000 --- a/docs/card_system_integration_and_testing.md +++ /dev/null @@ -1,159 +0,0 @@ -# Card System Integration and Testing Guide - -## Overview - -This document outlines the integration between the data and UI layers of the Apple Hills card collection system, as well as the testing tools available for development purposes. - -## Architecture Summary - -The card system follows a clean separation of concerns: - -1. **Data Layer** (Assets/Scripts/Data/CardSystem/) - - `CardSystemManager`: Singleton for managing card data, booster packs, and collection - - `CardInventory`: Player's collection of cards and booster packs - - `CardData`: Runtime instance of a collected card - - `CardDefinition`: ScriptableObject template defining card properties - - `CardVisualConfig`: Visual settings for cards based on rarity/zone - -2. **UI Layer** (Assets/Scripts/UI/CardSystem/) - - `CardAlbumUI`: Main controller for the card UI system - - `UIPageController`: Stack-based navigation system - - `UIPage`: Base class for UI pages with transition animations - - Page Components: - - `CardMenuPage`: Main menu for the card system - - `AlbumViewPage`: Grid display of collected cards with filtering - - `BoosterOpeningPage`: Interactive card reveal experience - - `CardUIElement`: Individual card visual representation - - `BoosterNotificationDot`: UI element showing booster pack counts - -## Integration Points - -### Initialization Process - -1. `CardSystemManager` initializes during the bootstrap process using `BootCompletionService` -2. UI components register with `BootCompletionService.RegisterInitAction()` for post-boot initialization -3. UI components access card data through `CardSystemManager.Instance` - -### Data Flow - -1. **Card Collection**: - - `CardSystemManager` manages the player's `CardInventory` - - Cards are added via `AddCardToInventory()` - - Card collection triggers `OnCardCollected` event - -2. **Booster Packs**: - - Added via `CardSystemManager.AddBoosterPack()` - - Opened via `CardSystemManager.OpenBoosterPack()` - - Booster count changes trigger `OnBoosterCountChanged` event - - Opening boosters triggers `OnBoosterOpened` event - -3. **Card Display**: - - `CardUIElement` displays a card using `SetupCard(cardData)` - - `AlbumViewPage` displays cards in a grid with filtering options - - `BoosterOpeningPage` handles interactive card reveals - -### Event System - -Key events that connect data and UI layers: - -- `OnBoosterCountChanged`: Triggered when booster count changes -- `OnBoosterOpened`: Triggered when a booster is opened -- `OnCardCollected`: Triggered when a new card is added to collection -- `OnCardRarityUpgraded`: Triggered when duplicates upgrade a card's rarity - -## Testing Tool: CardSystemTester - -The `CardSystemTester` provides a simple interface for testing the card system without requiring full game integration. - -### Features - -- Adding booster packs -- Opening the card menu -- Opening booster packs -- Browsing the album view -- Generating random test cards -- Clearing the card collection - -### Usage - -1. Add `CardSystemTester` component to a GameObject in your test scene -2. Reference the `CardAlbumUI` component -3. Enter Play mode and use the inspector buttons -4. All buttons are disabled in edit mode - -### Implementation Notes - -```csharp -public class CardSystemTester : MonoBehaviour -{ - // Only need reference to CardAlbumUI, the CardSystemManager is accessed via singleton - [SerializeField] private CardAlbumUI cardAlbumUI; - - // Other variables for test configuration - [SerializeField] [Range(1, 10)] private int boosterPacksToAdd = 3; - [SerializeField] [Range(1, 100)] private int cardsToGenerate = 10; - - // All operations use CardSystemManager.Instance - public void AddBoosterPacks() { - CardSystemManager.Instance.AddBoosterPack(boosterPacksToAdd); - // Other operations... - } - - // Uses CardAlbumUI to simulate UI interactions - public void SimulateBackpackClick() { - // Trigger the backpack button's onClick event - } - - // Additional test methods... -} -``` - -### Test Scene Setup - -1. Create a new scene or use an existing test scene -2. Add a Canvas with proper UI configuration -3. Add the CardSystem prefab (containing CardAlbumUI) -4. Add the CardSystemTester component -5. Make sure you have card definitions configured - -## Current Implementation Status - -1. **Complete**: - - Core data management through `CardSystemManager` - - Card collection and inventory management - - Basic UI navigation system - - Booster pack opening flow - - Album view with filtering - -2. **Added API Methods**: - - `GetAllCardDefinitions()`: Returns list of all card definitions - - `GetCardInventory()`: Returns reference to player's card inventory - - `ClearAllCards()`: Resets the player's collection - - Various utility methods for filtering and statistics - -3. **UI Improvements**: - - Simplified card display in album view - - Properly integrated card reveal animations - - Back button functionality for all pages - -## Known Issues and Considerations - -1. **Performance**: Large collections may require optimization -2. **Save System**: Currently not implemented, needs integration with game save system -3. **Card Definition Loading**: Ensure card definitions are loaded before use -4. **Testing Workflow**: Test specific state scenarios using the CardSystemTester -5. **Animation Timing**: May need adjustment for smoother experience - -## Next Steps - -1. Implement save/load system for card collection -2. Add collection statistics display -3. Implement rarity-specific effects for card reveals -4. Create more comprehensive test coverage - -## Technical References - -- Bootstrap system: Use `BootCompletionService.RegisterInitAction(InitializePostBoot)` for initialization -- Data access: Always use `CardSystemManager.Instance` for data access -- Page navigation: Use `UIPageController.Instance.PushPage()` and `PopPage()` -- Card UI: Use `CardUIElement.SetupCard()` to configure card display diff --git a/docs/card_system_playbook.md b/docs/card_system_playbook.md new file mode 100644 index 00000000..2f0c3ba5 --- /dev/null +++ b/docs/card_system_playbook.md @@ -0,0 +1,340 @@ +# Apple Hills Card System – Designer Playbook + +This playbook is for designers working with the rarity‑based Card System in Apple Hills. It provides a high‑level architecture overview, fast TL;DR playbooks for common tasks (with code-first snippets), and deeper guidance on how the system fits together. + + +## Table of Contents +- [Architecture at a Glance](#architecture-at-a-glance) +- [TL;DR Playbooks (Code-First)](#tldr-playbooks-code-first) + - [Open Booster Packs](#open-booster-packs) + - [Grant a Specific Card](#grant-a-specific-card) + - [Query the Collection](#query-the-collection) + - [Configure Visuals by Code (optional)](#configure-visuals-by-code-optional) + - [Clear the Collection](#clear-the-collection) +- [Authoring with the Card Editor (No Manual Setup)](#authoring-with-the-card-editor-no-manual-setup) + - [What happens automatically (under the hood)](#what-happens-automatically-under-the-hood) +- [In-Depth Overview](#in-depth-overview) +- [Designer How‑Tos (Quick Reference)](#designer-how-tos-quick-reference) +- [Best Practices & Tips](#best-practices--tips) +- [Known Gaps](#known-gaps) +- [FAQ](#faq) +- [Technical Reference (Quick)](#technical-reference-quick) +- [Change Log](#change-log) + + +## Architecture at a Glance + +The system is split into two main layers with clear responsibilities and a lightweight event bridge. + +- Data Layer (`Assets/Scripts/Data/CardSystem`) + - `CardSystemManager` (singleton) + - Source of truth for all card definitions, booster logic, and player `CardInventory`. + - Emits events on collection changes and booster activity. + - `CardInventory` + - Player’s owned cards and booster pack counters. + - Utility APIs for filtering cards (by rarity, zone, etc.). + - `CardDefinition` (`ScriptableObject`) + - Authoring asset that defines a card (name, visuals, zone, rarity tiering). + - `CardData` + - Runtime instance of a card in the player collection (ID, rarity, copies owned, links back to `CardDefinition`). + - `CardVisualConfig` (`ScriptableObject`) + - Central mapping for rarity/zone → visual treatment (colors, frames, shapes). + +- UI Layer (`Assets/Scripts/UI/CardSystem`) + - `CardAlbumUI` + - Entry point for the card UI (menu, album browser, booster opening). + - `UIPageController` + `UIPage` + - Stack-based navigation (push/pop) and shared transitions. + - Page Components + - `CardMenuPage` – Card hub/menu + - `AlbumViewPage` – Grid album view with filter/sort options + - `BoosterOpeningPage` – Interactive three-card reveal + - `CardUIElement` + - Renders a single card using `CardData` and `CardVisualConfig` + - `BoosterNotificationDot` + - Shows available booster pack count + +- Events (Data ↔ UI) + - `OnBoosterCountChanged` + - `OnBoosterOpened` + - `OnCardCollected` + - `OnCardRarityUpgraded` + +- Lifecycle + - Initialize during boot: `BootCompletionService.RegisterInitAction(...)` + - `CardSystemManager.Instance` is the access point from UI and tools (e.g., `CardSystemTester`) + + +## TL;DR Playbooks (Code-First) + +These are the most common tasks you’ll perform in code. Paste the snippets into a temporary test `MonoBehaviour`, a unit test, or hook them into your gameplay systems. + +### Open Booster Packs +```csharp +using AppleHills.Data.CardSystem; +using UnityEngine; + +public class BoosterOpenerSample : MonoBehaviour +{ + private void Start() + { + // Subscribe to events (optional, for feedback/UI updates) + CardSystemManager.Instance.OnBoosterOpened += cards => + { + Debug.Log($"Opened booster with {cards.Count} cards"); + }; + CardSystemManager.Instance.OnCardCollected += card => + { + Debug.Log($"Collected: {card.Definition.Name} (rarity: {card.Rarity})"); + }; + CardSystemManager.Instance.OnCardRarityUpgraded += card => + { + Debug.Log($"Upgraded rarity: {card.Definition.Name} -> {card.Rarity}"); + }; + + // Give the player some boosters and open one + CardSystemManager.Instance.AddBoosterPack(1); + var revealed = CardSystemManager.Instance.OpenBoosterPack(); + foreach (var cd in revealed) + { + Debug.Log($"Revealed: {cd.Definition.Name}"); + } + } +} +``` + +### Grant a Specific Card +```csharp +using System.Linq; +using AppleHills.Data.CardSystem; +using UnityEngine; + +public class GrantCardSample : MonoBehaviour +{ + [SerializeField] private string cardName = "Apple Picker"; // example + + private void Start() + { + var def = CardSystemManager.Instance + .GetAllCardDefinitions() + .FirstOrDefault(d => d.Name == cardName); + if (def == null) + { + Debug.LogWarning($"CardDefinition not found: {cardName}"); + return; + } + + var cardData = CardSystemManager.Instance.AddCardToInventory(def); + Debug.Log($"Granted: {cardData.Definition.Name} (copies: {cardData.CopiesOwned})"); + } +} +``` + +### Query the Collection +```csharp +using AppleHills.Data.CardSystem; +using UnityEngine; + +public class QueryCollectionSample : MonoBehaviour +{ + private void Start() + { + var inv = CardSystemManager.Instance.GetCardInventory(); + + // All cards + var all = inv.GetAllCards(); + Debug.Log($"Total cards owned: {all.Count}"); + + // By rarity (example) + var rares = inv.GetByRarity(CardRarity.Rare); + Debug.Log($"Rares: {rares.Count}"); + + // By zone (example) + var forest = inv.GetByZone(CardZone.Forest); + Debug.Log($"Forest: {forest.Count}"); + + // Counts (progression checks) + var byRarity = inv.CountByRarity(); + var byZone = inv.CountByZone(); + // Iterate dictionaries as needed + } +} +``` + +### Clear the Collection +```csharp +using AppleHills.Data.CardSystem; +using UnityEngine; + +public class ClearCollectionSample : MonoBehaviour +{ + private void Start() + { + CardSystemManager.Instance.ClearAllCards(); + Debug.Log("Card collection cleared (dev/test only)."); + } +} +``` + + +## Authoring with the Card Editor (No Manual Setup) +Designers should use the dedicated editor window: `AppleHills/Card Editor`. + +- Open via Unity menu: `AppleHills/Card Editor` (menu path defined in `CardEditorWindow`) +- The window provides a card list, detail editor, and a live preview of the UI card. +- You don’t need to create folders or assets manually—the tool handles setup and discovery. + +### What happens automatically (under the hood) +The `Assets/Editor/CardSystem/CardEditorWindow.cs` implements the following behaviors: +- Ensures the data directory exists: `Assets/Data/Cards` (creates it on first run). +- Discovers all `CardDefinition` assets under `Assets/Data/Cards` automatically via `AssetDatabase.FindAssets("t:CardDefinition")` and keeps the list sorted by `Name`. +- Creates new card assets as `Card_.asset` inside `Assets/Data/Cards`. +- Loads a UI preview prefab from `Assets/Prefabs/UI/Cards/SIngleCardDisplayUI.prefab` to render a live card preview inside the editor using `PreviewRenderUtility`. +- Tries to load `CardVisualConfig` at `Assets/Data/Cards/CardVisualConfig.asset` for consistent rarity/zone styling in the preview. +- Responds to Undo/Redo and Editor recompiles to stay in sync. +- When you duplicate or delete cards from the window, the corresponding assets are created/removed accordingly. + +Result: Designers focus on content (name, description, zone, art, etc.) in the Card Editor. The system takes care of folders, discovery, previewing, and syncing definitions with runtime. + + +## In-Depth Overview + +Data Layer Details +- `CardDefinition` (authoring) + - What it is: a `ScriptableObject` that defines a card’s identity and static presentation (name, description, zone, default visuals). + - Typical fields: `Name`, `Description`, `Zone`, rarity metadata, sprites/textures, optional tags. + - Helpers: `CreateCardData()` to generate a runtime `CardData` instance for inventory. + +- `CardData` (runtime instance) + - Purpose: Represents what the player owns – unique ID, rarity state, copies owned. + - Behavior: When duplicates are collected, `CardData` may upgrade rarity (e.g., duplicate thresholds). + - Links: Holds reference to its `CardDefinition` for display and classification. + +- `CardInventory` (player collection) + - Responsibilities: Store cards, track counts, support filters/lookups (by rarity/zone), manage booster counters. + - Common operations: `AddCard(def)`, `GetAllCards()`, `GetByRarity()`, `GetByZone()`, `CountByRarity()`, `CountByZone()`. + - Notes: Designed for efficiency and clarity; returns collections for the UI to display. + +- `CardSystemManager` (singleton coordinator) + - Responsibilities: Owns `CardInventory`, holds the card definition catalog, controls booster generation/opening, exposes public APIs. + - Events: `OnBoosterCountChanged`, `OnBoosterOpened`, `OnCardCollected`, `OnCardRarityUpgraded`. + - Typical APIs: + - `GetAllCardDefinitions()` → `IReadOnlyList` + - `GetCardInventory()` → `CardInventory` + - `AddBoosterPack(int count)` + - `OpenBoosterPack()` → `List` (or similar) + - `AddCardToInventory(CardDefinition def)` + - `ClearAllCards()` + +- `CardVisualConfig` (visual mappings) + - Purpose: Central place to establish the brand/look per rarity and zone. + - Implementation: `ScriptableObject` with dictionaries for quick lookups by rarity/zone. + +UI Layer Details +- `UIPageController` + `UIPage` + - Navigation: `PushPage(page)`, `PopPage()`, `Clear()`; optional transition animations. + - Pattern: Each page is a `UIPage` subclass registered under `CardAlbumUI`. + +- `CardAlbumUI` (system entry) + - Role: Wires pages together, responds to `CardSystemManager` events, routes to `AlbumViewPage` or `BoosterOpeningPage`. + +- `AlbumViewPage` + - Role: Displays a grid of `CardUIElement` items from `CardInventory` with filtering/sorting UI. + - Notes: Uses TextMeshPro components and simplified presentation (no stack/slot system). + +- `BoosterOpeningPage` + - Role: Handles the interactive reveal flow for 3 cards per booster; flip animations, particle FX, rarity feedback. + - Notes: Timings and art are still under refinement; supports individual reveal clicks. + +- `CardUIElement` + - Role: Displays a single `CardData` – name, art, frame, rarity chips, zone styling. + - Data Source: Uses `CardVisualConfig` for color/frame mapping. + +- `BoosterNotificationDot` + - Role: Indicates current booster count; listens to `OnBoosterCountChanged`. + +Event Flow Examples +- Opening a booster + - Player code calls `CardSystemManager.OpenBoosterPack()` → generates/awards 3 cards → raises `OnBoosterOpened`. + - Inventory updated; for each card, `OnCardCollected` (and maybe `OnCardRarityUpgraded`) fires. + - `BoosterOpeningPage` animates reveals; `AlbumViewPage` updates when returning. + +- Adding a card via quest reward + - Gameplay script calls `AddCardToInventory(def)`. + - Inventory updates; events fire to update UI. + +Rarity & Duplicates +- The system tracks copies owned per card. +- Duplicates can trigger rarity upgrades based on thresholds (implemented in `CardData`). +- UI can react with special effects via `OnCardRarityUpgraded` (e.g., distinct VFX/SFX per rarity). + + +## Designer How‑Tos (Quick Reference) + +Author a New Card (use the editor tool) +1) Open `AppleHills/Card Editor`. +2) Click New/Duplicate, edit `Name`, `Description`, `Zone`, and assign art. +3) Save—asset is created as `Assets/Data/Cards/Card_.asset`. It’s auto-discovered by runtime. + +Grant a Card by Code (quest reward) +```csharp +CardSystemManager.Instance.AddCardToInventory(rewardDefinition); +``` + +Open a Booster by Code +```csharp +CardSystemManager.Instance.AddBoosterPack(1); +CardSystemManager.Instance.OpenBoosterPack(); +``` + +Filter Cards for a Page +```csharp +var inv = CardSystemManager.Instance.GetCardInventory(); +var list = inv.GetByZone(CardZone.Quarry); +``` + + +## Best Practices & Tips + +- Always access data via `CardSystemManager.Instance` to keep a single source of truth. +- Keep `CardDefinition` assets lightweight and consistent; use tags/zones for filtering. +- When adding new rarities/zones, update `CardVisualConfig` and verify UI styling. +- For smoother reveals, coordinate with VFX/SFX to differentiate rarities. +- Large collections: consider paging or virtualized grids if performance becomes a concern. + + +## Known Gaps + +- Save/Load not implemented – test sessions won’t persist player collection. +- Booster Opening polish (timings/art/audio) is ongoing. +- Collection statistics/achievements UI pending. + + +## FAQ + +- Q: My new `CardDefinition` doesn’t show up in the album. + - A: Ensure the asset is in `Assets/Data/Cards` (the editor tool places it there) and that definitions load before UI opens. Check the `CardSystemManager` discovery and your zones/rarities. + +- Q: How do I trigger the card UI from another part of the game? + - A: Use `CardAlbumUI`’s public entry points or route through your UI flow to push the relevant page via `UIPageController`. + +- Q: Can I guarantee a specific rarity in a booster for a tutorial? + - A: Add a temporary tutorial hook in `CardSystemManager` to override booster generation rules for guided moments, or directly grant specific `CardDefinition`s for the tutorial step. + +- Q: How do duplicates upgrade rarity? + - A: The logic lives in `CardData`; when copies cross thresholds, it fires `OnCardRarityUpgraded`. Coordinate with design to set thresholds and with UI to show feedback. + + +## Technical Reference (Quick) + +- Initialize after boot: `BootCompletionService.RegisterInitAction(InitializePostBoot)` +- Data access: `CardSystemManager.Instance` +- Navigation: `UIPageController.Instance.PushPage()` / `PopPage()` +- Show a card in UI: `CardUIElement.SetupCard(cardData)` +- Test harness: `CardSystemTester` (add to scene, link `CardAlbumUI`) + + +## Change Log + +- v1.1: Added Table of Contents, inline code formatting, code-first TL;DR playbooks, and an authoring section based on `CardEditorWindow`. +- v1.0: Initial designer playbook, aligned with Implementation Plan and Integration & Testing Guide. \ No newline at end of file diff --git a/docs/card_system_ui_setup_guide_updated.md b/docs/card_system_ui_setup_guide_updated.md deleted file mode 100644 index 068a1407..00000000 --- a/docs/card_system_ui_setup_guide_updated.md +++ /dev/null @@ -1,309 +0,0 @@ -# Card System UI Setup Guide - -This guide provides detailed instructions for setting up the Card System UI in Unity, organized into prefabs that can be easily maintained and modified. - -## Prefab Structure Overview - -The card system UI should be structured with a modular prefab approach: - -1. **Main Card System Prefab** - Contains the CardAlbumUI component and core structure -2. **Individual UI Page Prefabs** - Each page as its own prefab -3. **Card UI Prefab** - For card display and interaction - -## Detailed Prefab Structure - -### Main CardSystem Prefab - -``` -CardSystem (with CardAlbumUI component) -├── BackpackIcon (GameObject) -│ ├── BackpackImage (Image) -│ ├── BoosterCountText (TextMeshProUGUI) -│ └── NotificationDot (GameObject with Image) -├── UIPageController (automatically added by CardAlbumUI if not present) -└── Notifications (GameObject) - └── NewCardNotification (GameObject) - ├── Background (Image) - └── Text (TextMeshProUGUI) -``` - -### Page Prefabs - -**1. MainMenuPage Prefab:** -``` -MainMenuPage (with CardMenuPage component & CanvasGroup) -├── Background (Image) -├── Title (TextMeshProUGUI) -├── OpenBoosterButton (Button) -│ └── Text (TextMeshProUGUI) -├── ViewAlbumButton (Button) -│ └── Text (TextMeshProUGUI) -├── ChangeClothesButton (Button) -│ └── Text (TextMeshProUGUI) -└── NoBoostersMessage (GameObject) - └── Text (TextMeshProUGUI) -``` - -**2. AlbumViewPage Prefab:** -``` -AlbumViewPage (with AlbumViewPage component & CanvasGroup) -├── Background (Image) -├── FilterPanel (GameObject) -│ ├── ZoneFilterDropdown (TMP_Dropdown) -│ │ ├── Label (TextMeshProUGUI) -│ │ └── Arrow (Image) -│ ├── RarityFilterDropdown (TMP_Dropdown) -│ │ ├── Label (TextMeshProUGUI) -│ │ └── Arrow (Image) -│ └── ResetFiltersButton (Button) -│ └── Text (TextMeshProUGUI) -├── AlbumScrollView (ScrollRect) -│ └── AlbumGrid (GridLayoutGroup) -``` - -**3. BoosterOpeningPage Prefab:** -``` -BoosterOpeningPage (with BoosterOpeningPage component & CanvasGroup) -├── Background (Image) -├── BoosterPackObject (GameObject) -│ └── BoosterImage (Image) -├── CardRevealContainer (RectTransform) -│ ├── CardRevealPosition1 (Transform) -│ ├── CardRevealPosition2 (Transform) -│ └── CardRevealPosition3 (Transform) -├── OpenBoosterButton (Button) -│ └── Text (TextMeshProUGUI) -├── ContinueButton (Button) -│ └── Text (TextMeshProUGUI) -├── CardRevealSound (AudioSource) -├── RareCardSound (AudioSource) -├── CardRevealParticles (ParticleSystem) -└── RareCardParticles (ParticleSystem) -``` - -### Card-Related Prefabs - -**1. CardPrefab:** -``` -Card (with CardUIElement component & Button) -├── CardBackground (Image) -├── CardFrame (Image) -├── CardImage (Image) -├── CardNameText (TextMeshProUGUI) -├── CardDescriptionText (TextMeshProUGUI) -├── ZoneLabel (TextMeshProUGUI) -└── RarityIndicator (Image) -``` - -**2. CardBackPrefab:** -``` -CardBack (with Button component) -├── CardBackImage (Image) -└── BackDesign (Image) -``` - -## Component Setup Guide - -### CardAlbumUI Component Setup - -This is the central controller for the card system: - -``` -CardAlbumUI Component Inspector: -- UI References: - - Backpack Icon: [BackpackIcon GameObject] - - Main Menu Page: [MainMenuPage Prefab] - - Album View Page: [AlbumViewPage Prefab] - - Booster Opening Page: [BoosterOpeningPage Prefab] -- UI Elements: - - Backpack Button: [BackpackIcon Button Component] - - Booster Count Text: [BoosterCountText Component] - - Notification Dot: [NotificationDot GameObject] - - Backpack Animation Target: [BackpackIcon Transform] - - New Card Notification: [NewCardNotification GameObject] -- Notification Settings: - - Notification Duration: 3 seconds (adjustable) - - Notification Sound: [AudioSource Component] -``` - -### CardMenuPage Component Setup - -``` -CardMenuPage Component Inspector: -- Menu Options: - - Open Booster Button: [OpenBoosterButton] - - View Album Button: [ViewAlbumButton] - - Change Clothes Button: [ChangeClothesButton] -- UI Elements: - - Booster Count Text: [BoosterCountText] - - No Boosters Message: [NoBoostersMessage] - - Canvas Group: [CanvasGroup on this GameObject] -``` - -### AlbumViewPage Component Setup - -``` -AlbumViewPage Component Inspector: -- Album UI Elements: - - Album Grid: [AlbumGrid Component] - - Card Prefab: [CardPrefab Asset] -- Filter UI: - - Zone Filter Dropdown: [ZoneFilterDropdown] - - Rarity Filter Dropdown: [RarityFilterDropdown] - - Reset Filters Button: [ResetFiltersButton] - - Canvas Group: [CanvasGroup on this GameObject] -``` - -### BoosterOpeningPage Component Setup - -``` -BoosterOpeningPage Component Inspector: -- UI Elements: - - Booster Pack Object: [BoosterPackObject] - - Card Reveal Container: [CardRevealContainer] - - Card Reveal Positions: [Array of 3 Transform positions] - - Card Prefab: [CardPrefab Asset] - - Card Back Prefab: [CardBackPrefab Asset] - - Open Booster Button: [OpenBoosterButton] - - Continue Button: [ContinueButton] - - Canvas Group: [CanvasGroup on this GameObject] - - Open Booster Text: [TextMeshProUGUI] - - Continue Text: [TextMeshProUGUI] -- Animation Settings: - - Card Reveal Delay: 0.3 (adjustable) - - Card Move To Backpack Delay: 0.8 (adjustable) - - Flip Animation Duration: 0.5 (adjustable) - - Backpack Target Transform: [BackpackIcon Transform] - - Card Reveal Sound: [CardRevealSound Component] - - Rare Card Sound: [RareCardSound Component] - - Card Reveal Particles: [CardRevealParticles Component] - - Rare Card Particles: [RareCardParticles Component] -``` - -### CardUIElement Component Setup - -``` -CardUIElement Component Inspector: -- Card UI Elements: - - Card Background Image: [CardBackground Image] - - Card Frame Image: [CardFrame Image] - - Card Image: [CardImage] - - Card Name Text: [CardNameText] - - Card Description Text: [CardDescriptionText] - - Zone Label: [ZoneLabel Text] - - Rarity Label: [RarityIndicator Image] -``` - -## Prefab Creation Process - -### 1. Create Card-Related Prefabs First - -Start by creating the card prefabs since other prefabs will reference them: - -1. **Create CardPrefab**: - - Create GameObject → UI → Image (for background) - - Add child Images for frame and card art - - Add TextMeshPro components for name, description, zone - - Add CardUIElement script - - Configure Inspector references - - Add Button component - - Save as prefab - -2. **Create CardBackPrefab**: - - Create GameObject → UI → Image (for card back) - - Add Button component for interaction - - Style appropriately to match your game's aesthetics - - Save as prefab - -### 2. Create UI Page Prefabs - -Create each page prefab individually: - -1. **Create MainMenuPage Prefab**: - - Set up UI elements as shown in structure - - Add CardMenuPage script - - Add CanvasGroup component - - Configure all Inspector references - - Save as prefab - -2. **Create AlbumViewPage Prefab**: - - Set up UI elements as shown in structure - - Add AlbumViewPage script - - Add CanvasGroup component - - Configure all Inspector references - - Assign CardPrefab - - Save as prefab - -3. **Create BoosterOpeningPage Prefab**: - - Set up UI elements as shown in structure - - Create CardRevealContainer with three child positions - - Add BoosterOpeningPage script - - Add CanvasGroup component - - Add audio sources and particle systems - - Configure all Inspector references - - Assign CardPrefab and CardBackPrefab - - Save as prefab - -### 3. Create Main CardSystem Prefab - -Finally, create the main controller prefab: - -1. **Create CardSystem GameObject**: - - Add CardAlbumUI script - - Set up BackpackIcon and Notifications as shown in structure - - Assign references to page prefabs (not instances) - - Configure all Inspector references - - Save as prefab - -## Scene Setup Instructions - -### 1. Add CardSystem to Your Scene - -1. Drag the CardSystem prefab into your scene -2. Make sure it's on the UI layer -3. Verify it has a Canvas component if needed (or is under a Canvas) - -### 2. Configure the CardSystemManager - -1. Create a GameObject named "CardSystemManager" if not already present -2. Add the CardSystemManager script -3. Populate it with some test card definitions -4. Ensure it's marked as DontDestroyOnLoad if needed - -### 3. Test the System - -1. Enter Play mode -2. Test clicking the backpack icon -3. Add test booster packs: `CardSystemManager.Instance.AddBoosterPack(3)` -4. Test opening boosters and viewing the album - -## Additional Tips - -1. **Canvas Settings**: - - Set your Canvas to Screen Space - Overlay - - Use Scale With Screen Size with reference resolution 1920x1080 - - Configure the Canvas Scaler for proper UI scaling - -2. **UI Navigation**: - - Configure button navigation for keyboard/controller support - - Set tab order for accessibility - -3. **Audio Setup**: - - Keep audio sources on the respective UI elements - - Adjust spatial blend to 0 (2D) for UI sounds - - Use appropriate volume for notification sounds - -4. **Animation Considerations**: - - All animations use Pixelplacement.Tween - - Adjust animation durations in Inspector for fine-tuning - - Consider creating animation presets for consistent feel - -5. **Testing on Different Devices**: - - Test the UI on different aspect ratios - - Ensure UI elements are anchored properly for different resolutions - - Use the Device Simulator to test mobile layouts if targeting mobile - -6. **Performance Tips**: - - Consider object pooling for cards in large collections - - Disable raycast targets on non-interactive elements - - Use sprite atlases for card images diff --git a/docs/ui_page_navigation.md b/docs/ui_page_navigation.md new file mode 100644 index 00000000..d6e40eae --- /dev/null +++ b/docs/ui_page_navigation.md @@ -0,0 +1,194 @@ +# UI Page Navigation System + +A brief guide to the stack-based page navigation used across the project. It is built around `UIPageController` (the navigator) and `UIPage` (the base page with transition hooks). This system is used by the card collection UI and can be reused for any feature that needs push/pop navigation with transitions. + +- Source files: + - `Assets/Scripts/UI/Core/UIPageController.cs` + - `Assets/Scripts/UI/Core/UIPage.cs` + +## Table of Contents +- [Concepts](#concepts) +- [Quick Start](#quick-start) +- [Transitions and Events](#transitions-and-events) +- [Card System Case Studies](#card-system-case-studies) +- [Best Practices](#best-practices) +- [API Reference (Essentials)](#api-reference-essentials) + +## Concepts +- `UIPageController` + - A singleton navigator that maintains a stack of `UIPage` instances. + - Provides `PushPage`, `PopPage`, and `ClearStack`. + - Fires `OnPageChanged` when the top page changes. +- `UIPage` + - Base class for pages with overridable transition hooks. + - Implements `TransitionIn`, `TransitionOut`, and `OnBackPressed`. + - Comes with start/complete events for both in/out transitions. + +Stack behavior in short: +- `PushPage(page)` hides the current page (transition out), shows the new page (transition in), and puts it on top. +- `PopPage()` hides the current page (transition out), reveals the previous top page (transition in). + +## Quick Start + +### 1) Showing a page +```csharp +// Assuming you have a reference to a concrete UIPage (via scene object or instantiated prefab) +[SerializeField] private UIPage albumViewPage; + +void OpenAlbum() +{ + UIPageController.Instance.PushPage(albumViewPage); +} +``` + +### 2) Going back +```csharp +void Back() +{ + UIPageController.Instance.PopPage(); +} +``` + +### 3) Custom page with simple transitions +```csharp +using System; +using UnityEngine; + +public class FadePage : UIPage +{ + [SerializeField] private CanvasGroup canvasGroup; + + protected override void DoTransitionIn(Action onComplete) + { + // Example: simple fade in (pseudo-code; replace with your tween/anim system) + canvasGroup.alpha = 0f; + gameObject.SetActive(true); + // Tween to alpha 1 over transitionDuration, then: + onComplete?.Invoke(); + } + + protected override void DoTransitionOut(Action onComplete) + { + // Example: simple fade out + // Tween to alpha 0 over transitionDuration, then: + onComplete?.Invoke(); + // The base class will SetActive(false) after completion. + } +} +``` + +### 4) Wiring a generic Cancel/Back input (optional) +`UIPageController` has placeholders to wire a Cancel action from the Input System. If you want a global back action: +```csharp +// In your bootstrap or scene initializer +var controller = UIPageController.Instance; // ensure it exists in the scene +// Optionally hook up your own input and call: +if (controller.CurrentPage != null) +{ + controller.CurrentPage.OnBackPressed(); +} +``` + +## Transitions and Events + +`UIPage` exposes these events: +- `OnTransitionInStarted` +- `OnTransitionInCompleted` +- `OnTransitionOutStarted` +- `OnTransitionOutCompleted` + +Use them to coordinate animation, audio, or deferred loading. + +Example: enable input only after a page is visible. +```csharp +void OnEnable() +{ + albumViewPage.OnTransitionInCompleted += EnableAlbumInput; + albumViewPage.OnTransitionOutStarted += DisableAlbumInput; +} + +void OnDisable() +{ + albumViewPage.OnTransitionInCompleted -= EnableAlbumInput; + albumViewPage.OnTransitionOutStarted -= DisableAlbumInput; +} +``` + +## Card System Case Studies + +These examples show how the card UI uses the page stack. + +### Open the Card Menu from gameplay HUD +```csharp +[SerializeField] private UIPage cardMenuPage; + +public void OnBackpackButton() +{ + UIPageController.Instance.PushPage(cardMenuPage); +} +``` + +### Navigate from Card Menu to Album view +```csharp +[SerializeField] private UIPage albumViewPage; + +public void OnAlbumButton() +{ + UIPageController.Instance.PushPage(albumViewPage); +} +``` + +### Enter Booster Opening flow and then return +```csharp +[SerializeField] private UIPage boosterOpeningPage; + +public void OnOpenBooster() +{ + // Assume booster count was verified via `CardSystemManager` + UIPageController.Instance.PushPage(boosterOpeningPage); +} + +// Inside the booster opening page, when user taps Back or after completion +public override void OnBackPressed() +{ + if (!_isTransitioning) + { + // Optional: guard against leaving mid-reveal + // if (!revealComplete) return; + UIPageController.Instance.PopPage(); + } +} +``` + +### Close all card UI and return to HUD +```csharp +public void CloseAllCardUI() +{ + UIPageController.Instance.ClearStack(); +} +``` + +## Best Practices +- One active `UIPageController` per UI context (usually one in the main UI scene). Avoid multiple competing controllers. +- Keep transitions short and responsive; the base class already handles `SetActive` lifecycle for you. +- Always check `_isTransitioning` (available in `UIPage`) before triggering back/forward actions to avoid double navigations. +- Use `OnPageChanged` on `UIPageController` to manage global state (e.g., pause input when a modal page is shown). +- If you instantiate pages at runtime, ensure their `GameObject` is inactive by default and let `TransitionIn` activate them. + +## API Reference (Essentials) + +From `UIPageController`: +- `UIPage CurrentPage` — top of the stack or `null`. +- `event Action OnPageChanged` — fired after a push/pop resolves. +- `void PushPage(UIPage page)` — transitions out current (if any), transitions in the new page, pushes it on the stack. +- `void PopPage()` — transitions out current, reveals previous page with a transition in. +- `void ClearStack()` — transitions out current and empties the stack. + +From `UIPage`: +- `string PageName` — a designer-friendly name for logs/diagnostics. +- `float transitionDuration` (protected) — your animations can use this. +- `virtual void TransitionIn()` / `TransitionOut()` — call the overridable `DoTransitionIn`/`DoTransitionOut`. +- `virtual void OnBackPressed()` — default pops the page (calls `UIPageController.Instance.PopPage()`). Override to customize. +- Events: `OnTransitionInStarted`, `OnTransitionInCompleted`, `OnTransitionOutStarted`, `OnTransitionOutCompleted`. + +For additional context and examples, see `docs/card_system_playbook.md` and `docs/card_system_integration_and_testing.md`. \ No newline at end of file