Files
AppleHillsProduction/docs/ui_page_navigation.md

194 lines
6.3 KiB
Markdown
Raw Normal View History

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