Files
maplecontest/docs/card-ui-standardization.md

165 lines
3.6 KiB
Markdown

# Card UI Standardization
## Goal
Make every card-shaped UI use the same input structure so hover tooltip,
click, drag, and future interactions behave the same way everywhere.
Target surfaces:
- hand cards
- reward cards
- shop cards
- draw pile / discard pile / exhaust pile viewer cards
- all deck / class deck / codex cards
## Standard Card Entity Shape
Each visible card should have one root entity that owns input.
```text
CardRoot
- UITransformComponent
- SpriteGUIRendererComponent
- ButtonComponent
- UITouchReceiveComponent
- Cost
- Name
- Desc
- Art
```
Rules:
1. `CardRoot` covers the full card rect.
2. `CardRoot` owns both click and hover.
3. Child entities are display only.
4. Child entities must not become the primary input target.
## Required Component Rules
### Card root
- `UITransformComponent`
- `SpriteGUIRendererComponent`
- `ButtonComponent`
- `UITouchReceiveComponent`
Recommended sprite settings:
- `RaycastTarget: true`
- card frame sprite on root
### Card children
- `Cost`, `Name`, `Desc`: text only
- `Art`: sprite only
Recommended child sprite settings:
- `RaycastTarget: false`
That keeps hover/click ownership on the root card entity.
## Path Rules
Use the same path naming pattern everywhere:
- hand: `/ui/.../CardHand/Card1`
- reward: `/ui/.../RewardHud/Reward1`
- shop: `/ui/.../ShopHud/Card1`
- inspect: `/ui/.../DeckInspectHud/Grid/Card1`
- all deck: `/ui/.../DeckAllHud/Grid/Card1`
The important part is that each list has a stable root card path ending in a
numeric slot. That lets controller code resolve hover target -> slot -> card id
without special cases.
## Controller Rules
Once UI is standardized, controller logic should follow this shape:
1. Resolve `path`
2. Resolve `slot` from `path`
3. Resolve `cardId` from current backing list
4. Show tooltip from `cardId`
Preferred shared methods:
- `GetHoveredCardId(path)`
- `HoverCardByPath(path)`
- `UnhoverCardByPath(path)`
The hand should just become one caller of the same shared path-based hover
logic rather than having its own special tooltip flow.
## Safe Rollout Order
Do not standardize every card surface at once.
### Step 1
Document current structures for:
- `RewardHud/Reward1`
- `ShopHud/Card1`
- `DeckInspectHud/Grid/Card1`
- `DeckAllHud/Grid/Card1`
### Step 2
Make `DeckInspectHud/Grid/CardN` match `RewardHud/RewardN` component structure.
### Step 3
Verify game boot and UI load before changing controller hover bindings.
### Step 4
Make `DeckAllHud/Grid/CardN` match the same structure.
### Step 5
After both surfaces are stable, bind hover events in controller code.
## Validation Checklist
Before testing hover behavior:
- game boots with no `LEA-3015 CannotLoad`
- `DefaultGroup.ui` loads cleanly
- card roots exist at expected paths
- root card sprite has `RaycastTarget: true`
- child art sprite has `RaycastTarget: false`
- root has both `ButtonComponent` and `UITouchReceiveComponent`
After binding hover:
- hand tooltip still works
- reward tooltip still works
- shop tooltip still works
- inspect tooltip works
- all deck tooltip works
- no duplicated tooltip flicker
- no drag regression on hand cards
## What Not To Do
- do not hand-edit `ui/DefaultGroup.ui`
- do not change multiple card surfaces in one shot
- do not mix root-input cards with child-input cards
- do not add hover logic before confirming the target card entity actually
receives input
## Recommended Next Change
The next implementation step should be:
1. diff `DeckInspectHud/Grid/Card1` against `RewardHud/Reward1`
2. make only `DeckInspectHud` root card structure match
3. regenerate UI
4. boot test
5. then bind hover for inspect cards only
That keeps the blast radius small.