# 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`.