diff --git a/.cursor/rules/ui-framework.mdc b/.cursor/rules/ui-framework.mdc new file mode 100644 index 0000000..65f566c --- /dev/null +++ b/.cursor/rules/ui-framework.mdc @@ -0,0 +1,27 @@ +--- +description: UI work routing — read the AI framework index first, read scoped, don't scan the whole codebase +alwaysApply: true +--- + +# UI Framework: Scoped Reading + +For ANY UI task (components, HUD, panels, buttons, meters, menus, widgets under `Assets/UI/**`), follow this before reading code: + +1. **Read `AI/INDEX.md` first.** It is the router. Use its *Task → Read set* table. +2. **Open the ONE matching per-component doc** in `AI/components/.md`. Its **Files** section lists the exact code to read. +3. **Open only those listed files.** Do NOT grep or semantic-search `Assets/**` broadly. The docs already point to the right files. +4. **Budget:** a normal UI task = ≤ 4 docs + ≤ 6 code files. If you exceed this, you are off-route — return to `AI/INDEX.md`. +5. **Widen by one step only** (a component's direct dependencies listed in its doc) if truly needed — never the whole repo. +6. If no component doc matches and the task isn't in the router table, read `AI/README.md` once, then ask which component is in scope (RULES R-21). + +## Authoring rules (when creating/editing UI) + +- Obey `AI/RULES.md` (R-01…R-36). Key ones: search before create (R-05), duplicate-before-modify (R-02/R-03), tokens/`Style1*` (R-07/R-08), **Rhythm menu bar for all setup** (R-17), **runtime layout** (R-25–R-32), **edit-mode visible + saveable UI** (R-36), **register on the UI Component Gallery board via `[UIGalleryComponent]`** (R-37), **Inspector on controller** (R-31), **compile-check** (R-29, R-33), **interactive UI: EventSystem + raycast + Play lifecycle** (R-34). +- Every new component must match the **Score HUD standard**: … **Menus:** register under **`Rhythm → Setup …`** and **`Rhythm → Create … Demo Scene`** (`AI/WORKFLOW.md` → Rhythm menu bar). **Live access (mandatory):** every new component must be openable via **demo scene** and **UI Component Gallery board** — see `AI/WORKFLOW.md` → Live access gate. **Layout pitfalls:** `AI/WORKFLOW.md` → Runtime layout & wiring. **Scene view / save:** `AI/WORKFLOW.md` → Edit-mode visibility (R-36). **Pointer/hover/click:** `AI/WORKFLOW.md` → Interactive UI checklist (R-34). +- After changes: update the component doc + `AI/INDEX.md` + `AI/COMPONENT_INDEX.md` (R-11), then `AI/CHANGELOG.md` (R-13). + +## Do NOT + +- Do not read all of `AI/*.md` at once "to be safe" — use the router. +- Do not open unrelated systems (Tree, Rhythm core, PrimeTween internals) unless a component doc lists them. +- Do not invent colors/sizes/timings — they live in `AI/TOKEN_INDEX.md`. diff --git a/.gitignore b/.gitignore index e77622b..d2ca4ca 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ # Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore # .utmp/ +.DS_Store +**/.DS_Store +.tmp_ptween/ /[Ll]ibrary/ /[Tt]emp/ /[Oo]bj/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3b97949 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "Unity-Extensions"] + path = Unity-Extensions + url = https://github.com/Privnoval016/Unity-Extensions.git +[submodule "Assets/Extensions"] + path = Assets/Extensions + url = https://github.com/Privnoval016/Unity-Extensions.git diff --git a/AI/ANIMATION_INDEX.md b/AI/ANIMATION_INDEX.md new file mode 100644 index 0000000..f2ec4c5 --- /dev/null +++ b/AI/ANIMATION_INDEX.md @@ -0,0 +1,286 @@ +# ANIMATION_INDEX + +> A searchable registry of every animation in the project. Its purpose is to make **reuse the default** and recreation the exception ([RULES.md](./RULES.md) R-09). +> Before authoring any motion, search here by effect. If a match's **Can Reuse = Yes**, use it. +> Related: [TOKEN_INDEX.md → Animation](./TOKEN_INDEX.md#4-animation-tokens) · [STYLE.md → Motion](./STYLE.md#16-animation-timing) · [WORKFLOW.md → Animation Reuse](./WORKFLOW.md#animation-reuse) + +--- + +## How animation is done here + +All motion uses **PrimeTween** (`Assets/Plugins/PrimeTween/`) called directly from controllers (no Animator clips for these). The reference implementations live in `Assets/UI/ScoreHUDController.cs`. Durations and easings are **tokens** ([TOKEN_INDEX.md](./TOKEN_INDEX.md)); never inline literals (R-08). + +### Reuse rules + +1. Search by **effect keyword** (squash, pop, fade, rise, float, shake). +2. If `Can Reuse = Yes`, call the existing routine / replicate via the shared helper and add your component to **Used By**. +3. If nothing matches, check **Related Animations** before authoring new motion. +4. Register every genuinely new animation here (R-09, R-11). + +### Entry schema + +**Name · Duration · Curve · Trigger · Used By · Can Reuse · Related Animations · Notes** + +--- + +## Registry + +### score-count-up +- **Duration:** `anim.duration.base` (0.32s) +- **Curve:** `ease.decelerate` (OutCubic) +- **Trigger:** Score value changes (`OnScoreUpdated`) +- **Used By:** Score HUD (`AnimateScoreTo`) +- **Can Reuse:** Yes — any numeric readout that should tween between values +- **Related Animations:** value-pop +- **Notes:** `Tween.Custom` interpolates `long` start→target, calls `SetScoreText`. Stops any in-flight count tween first. Reuse for currency, health numbers, timers. + +### value-pop +- **Duration:** `anim.duration.fast` in → `anim.duration.settle` out (0.12s → 0.22s) +- **Curve:** `ease.back` (OutBack) in, `ease.elastic` (OutElastic) settle +- **Trigger:** Successful hit / value emphasis +- **Used By:** Score HUD (`PlayStyle1HitMotion`, score value rect) +- **Can Reuse:** Yes — emphasize any element when its value updates +- **Related Animations:** score-count-up, panel-squash, combo-pop +- **Notes:** Scale base→`anim.press.scale` (1.16) then spring back to base. `Tween.StopAll` + reset scale before starting to avoid compounding. + +### panel-squash +- **Duration:** ~0.12 → 0.28 → 0.18s chained +- **Curve:** OutQuad → OutElastic → OutQuad +- **Trigger:** Hit on a panel/card +- **Used By:** Score HUD (`PlayStyle1HitMotion`, panel root) +- **Can Reuse:** Yes — any card/panel reacting to an event +- **Related Animations:** value-pop, shadow-bounce +- **Notes:** Squash `(1.04, 0.92)` → overshoot `(0.98, 1.05)` → base. Classic juice; pair with shadow-bounce. + +### shadow-bounce +- **Duration:** 0.2 → 0.25s chained +- **Curve:** `ease.elastic` out, `ease.standard` back +- **Trigger:** Hit (accompanies panel-squash) +- **Used By:** Score HUD (`PlayStyle1HitMotion`, shadow rect) +- **Can Reuse:** Yes — any element using the hard-shadow elevation model +- **Related Animations:** panel-squash +- **Notes:** Animates shadow `offsetMin/offsetMax` from rest to `+ (2,-2)` and back. Ties to `elevation.pressed` token. + +### combo-pop +- **Duration:** 0.10 → 0.20s chained +- **Curve:** OutBack → OutElastic +- **Trigger:** Combo count increases (≥2) +- **Used By:** Score HUD (`UpdateComboText`) +- **Can Reuse:** Yes — streak/multiplier emphasis +- **Related Animations:** value-pop, combo-break +- **Notes:** Scale `1.14x` then settle. Only fires when `Combo > _lastCombo`. + +### combo-break +- **Duration:** scale 0.12 → 0.28s; color 0.45s +- **Curve:** OutBack → OutElastic (scale), OutQuad (color) +- **Trigger:** Combo broken (`OnComboBreak`) +- **Used By:** Score HUD (`OnComboBreak`) +- **Can Reuse:** Yes — any "streak lost / negative" feedback +- **Related Animations:** combo-pop +- **Notes:** Flashes `color.feedback.danger` + text "COMBO BREAK", scales, then color-tweens back to combo color and clears after delay. Pairs color **and** text (a11y, never color-only). + +### praise-popup +- **Duration:** `anim.duration.popup` (0.85s); fade-in 0.12s +- **Curve:** OutQuad (fade in) → InQuad (fade out); OutCubic (rise); OutBack (scale-in) +- **Trigger:** Hit with praise enabled (`SpawnPraisePopup`) +- **Used By:** Score HUD (PERFECT/GREAT/GOOD popups) +- **Can Reuse:** Yes — floating feedback labels, damage numbers, toasts +- **Related Animations:** value-pop +- **Notes:** Clones a hidden `PopupTemplate`, fades + rises (`anim.popup.rise` 52) + drifts (`anim.popup.drift` 12), scales in, destroys on complete. The canonical "spawn transient label" routine. + +### idle-float +- **Duration:** `anim.duration.idle` (5s), looped Yoyo +- **Curve:** `ease.smooth` (InOutSine) +- **Trigger:** Component initialized & visible (`StartIdleFloat`) +- **Used By:** Score HUD (whole panel) +- **Can Reuse:** Yes — ambient life for any floating panel/card +- **Related Animations:** — +- **Notes:** Bobs anchored Y by `anim.idle.amplitude` (4). Infinite loop (`-1`, `CycleMode.Yoyo`); must be stoppable for "reduce motion" (a11y). Resets to rest position on stop. + +### bouncy-hit +- **Duration:** ~0.1 → 0.22 → 0.18 → 0.24s chained (+ rotation/position in parallel) +- **Curve:** OutQuad → OutElastic chains; rotation OutBack/OutElastic +- **Trigger:** Hit on bouncy score HUD (`PlayBouncyHitMotion`) +- **Used By:** — *(removed; reuse when recreating bouncy HUD variant)* +- **Can Reuse:** Yes — exaggerated card reaction (squash + tilt + upward punch + shadow slam) +- **Related Animations:** panel-squash, shadow-bounce, value-pop +- **Notes:** Panel squash to `(1.16, 0.74)` → overshoot `(0.9, 1.24)` + ±9° Z wobble + 14px upward root punch. Tune via Inspector `_panelSquashX/Y`, `_panelTiltDegrees`, `_positionPunch`. + +### bouncy-value-pop +- **Duration:** 0.1 → 0.12 → 0.32s +- **Curve:** OutBack → InQuad → OutElastic +- **Trigger:** Hit (score value rect) +- **Used By:** Score HUD Bouncy *(removed)* +- **Can Reuse:** Yes — extreme numeric pop with rotation wobble +- **Related Animations:** value-pop +- **Notes:** Scale to 1.38× with rotation wobble. Default `_valuePopScale` in Inspector. + +### bouncy-combo-break +- **Duration:** scale 0.1→0.14→0.36s; rotation 0.1→0.16→0.22s; color 0.5s +- **Curve:** OutBack → InQuad → OutElastic (scale); OutBack/OutElastic (rotation) +- **Trigger:** Combo broken on bouncy HUD +- **Used By:** Score HUD Bouncy *(removed)* +- **Can Reuse:** Yes — violent negative feedback with rotation shake +- **Related Animations:** combo-break +- **Notes:** Pairs red text with scale + ±12°/8° rotation shake. + +### bouncy-praise-popup +- **Duration:** `anim.duration.popup` (~0.95s) +- **Curve:** OutBack fade-in; OutElastic scale; OutBack travel +- **Trigger:** Hit with praise enabled on bouncy HUD +- **Used By:** Score HUD Bouncy *(removed)* +- **Can Reuse:** Yes — spinning elastic toast +- **Related Animations:** praise-popup +- **Notes:** Starts at 0.55 scale, elastic to 1.12→1.0, spins `_popupSpinDegrees` while rising 72px. + +### marquee-scroll +- **Duration:** variable — `scrollDist / 120` s (canvas units/s at rate 120; ~0.5–3s for typical labels) +- **Curve:** `ease.smooth` (InOutSine) both directions +- **Trigger:** `MarqueeLabel.SetText` — fires when `preferredWidth > containerWidth - 2×space.md` at the current font size, after `ForceMeshUpdate(true)` +- **Used By:** `MarqueeLabel` — TitleMarquee, AuthorMarquee, AlbumMarquee on `SongCardView` +- **Can Reuse:** Yes — wrap any TMP label in `MarqueeLabel` for automatic overflow handling +- **Related Animations:** idle-float +- **Notes:** Ping-pong via `Tween.Custom` on `anchoredPosition.x` (left-pinned fixed-width layout during scroll; stretches back on reset). `RectMask2D` on the container clips overflow cleanly. Pauses `kPauseSec = 1.2s` at each end. Cancelled immediately (`_cts.Cancel()`) on `SetText`, `OnDisable`, `OnDestroy`. `ForceMeshUpdate(true)` is mandatory before reading `preferredWidth` — skipping it causes the measure to return 0. + +--- + +### `button-hover-lift` +- **Duration:** 0.14s · **Curve:** `ease.outCubic` · **Trigger:** Pointer enter/exit on `Style1Button` +- **Used By:** Style 1 Button, Main Menu +- **Can Reuse:** Yes · **Related:** hover-tint, shadow-bounce +- **Notes:** VisualRoot lifts Y + scale 1.02; shadow offset grows; fill/label tint toward accent. `Style1Button._hoverDuration`, `_hoverLiftY`. + +### `button-press-squash` +- **Duration:** 0.09s down / 0.32s release · **Curve:** `ease.outQuad` / `ease.outElastic` · **Trigger:** Pointer down/up on `Style1Button` +- **Used By:** Style 1 Button, Main Menu +- **Can Reuse:** Yes · **Related:** press-squash, value-pop, panel-squash +- **Notes:** Squash scale (1.06, 0.84), sink Y, shadow compress, accent fill; elastic release on up. + +### tree-node-enter + +- **Duration:** `anim.duration.tree.node.in` (0.30s) per node; stagger `anim.duration.tree.stagger` (0.08s) × depth +- **Curve:** `ease.back` (OutBack) +- **Trigger:** `MenuTreeController.PushRoot` or `MenuTreeController.PushSubTree` +- **Used By:** `MenuTreeController` (title screen tree nodes) +- **Can Reuse:** Yes — any world-space node that needs to appear with a pop-in +- **Related Animations:** value-pop, fade-scale-in, tree-node-exit +- **Notes:** Scale `0→base` + alpha `0→1` via `MaterialPropertyBlock._BaseColor.a`. Stagger computed as `depthIndex × stagger`. Deepest nodes appear last. + +### tree-node-exit + +- **Duration:** `anim.duration.tree.node.out` (0.20s), all nodes simultaneously +- **Curve:** `ease.standard` (OutQuad) +- **Trigger:** `MenuTreeController.PopLevel` or tree swap +- **Used By:** `MenuTreeController` +- **Can Reuse:** Yes — dismiss world-space nodes +- **Related Animations:** tree-node-enter, fade-out +- **Notes:** Scale `base→0` + alpha `1→0` in parallel. After completion: destroy edge parent GO, release views. A `anim.duration.subtree.overlap` (0.10s) overlap lets the incoming tree start before this finishes. + +### tree-cursor-move + +- **Duration:** `anim.duration.fast` (0.15s) +- **Curve:** `ease.standard` (OutQuad) +- **Trigger:** `MenuTreeController.SetCursor` on each `OnCursorMoved` event from navigator +- **Used By:** `MenuTreeController` +- **Can Reuse:** Yes — highlight "selected" node in any menu +- **Related Animations:** value-pop +- **Notes:** `NodeVisualState.ComparisonFocus` applied to new cursor node (shows ring). `PulseAsync(1.08f, 0.15f, OutQuad)` on new node. Previous node goes to `NodeVisualState.Normal`. + +### tree-node-confirm + +- **Duration:** `anim.duration.fast` (0.12s) + `anim.duration.settle` (0.28s) +- **Curve:** `ease.back` → `ease.elastic` +- **Trigger:** Confirm input on a cursor-focused node +- **Used By:** `TitleTreeState` (fires before `OnConfirmLeaf` or `PushSubTree`) +- **Can Reuse:** Yes — confirm animation on any interactive world-space element +- **Related Animations:** tree-cursor-move, value-pop +- **Notes:** `PulseAsync(1.2f, 0.4f, OutElastic)` on the confirmed node before the side-effect fires. Gives visual confirmation before the screen changes. + +### header-label-swap + +- **Duration:** `anim.duration.header.swap` (0.20s) out + 0.20s in +- **Curve:** `ease.in` (InQuad) out, `ease.standard` (OutQuad) in +- **Trigger:** `MenuSceneController.ShowSongSelect()` / `ShowTitle()` header text change +- **Used By:** `MenuSceneController` +- **Can Reuse:** Yes — any label that needs a text change with a short fade +- **Related Animations:** fade-out, fade-scale-in +- **Notes:** CanvasGroup alpha `1→0` (0.2s), change `TMP_Text.text`, then `0→1` (0.2s). Total 0.4s. Use for any persistent header that changes content between states. + +### menu-section-fade + +- **Duration:** 0.20s out / 0.25s in +- **Curve:** `ease.in` (InQuad) out, `ease.standard` (OutQuad) in +- **Trigger:** `MenuSceneController.ShowSongSelect()` / `ShowTitle()` +- **Used By:** `MenuSceneController` (`_titleGroup`, `_songSelectGroup` CanvasGroups) +- **Can Reuse:** Yes — any CanvasGroup section that needs to swap visibility +- **Related Animations:** header-label-swap, fade-out +- **Notes:** Simultaneous alpha tweens on two CanvasGroups. The outgoing group finishes (alpha=0) before the incoming group's tween is halfway done — this creates an intentional brief gap, not overlap, to keep the transition clean. + +### background-color-cycle + +- **Duration:** `_colorCyclePeriod` (60s default), continuous loop +- **Curve:** Linear (using `Mathf.PingPong`) +- **Trigger:** Always-on when `SynthwaveBackgroundController._enableColorCycle = true` +- **Used By:** `SynthwaveBackgroundController` (Menu scene only) +- **Can Reuse:** — (self-contained in controller) +- **Related Animations:** — +- **Notes:** Hue cycles 220°(blue)→320°(pink) via `Mathf.Lerp(hueA, hueB, Mathf.PingPong(t*2,1))`. Affects `SkyTopColor`, `HorizonColor`, `GridColor` only — UI elements are unaffected. Period configurable per Inspector. + +### menu-beat-pulse + +- **Duration:** Instantaneous set; decay via `Mathf.Exp(-_beatRelease * dt)` +- **Curve:** Exponential decay +- **Trigger:** `MenuBeatTimer.OnBeat` event (driven by hovered song's BPM) +- **Used By:** `SynthwaveBackgroundController` in Menu scene via `_menuBeatTimer` reference +- **Can Reuse:** — (hooks into existing `_beatPulse` decay in `SynthwaveBackgroundController`) +- **Related Animations:** background-color-cycle +- **Notes:** Identical to the game-scene `TreeRhythmController.OnBeat` path — same `_beatPulse` float, same exponential decay formula. In the Menu scene, driven by `MenuBeatTimer` (which fires at song BPM) rather than `TreeRhythmController`. Controller subscribes to whichever source is non-null. + +--- + +## Template entries (author when first needed) + +> Reserve standard names so future components reuse instead of reinventing. + +### `[TEMPLATE] hover-tint` +- **Duration:** `anim.hover.duration` (~0.12s) · **Curve:** `ease.standard` · **Trigger:** Pointer enter/exit +- **Used By:** — · **Can Reuse:** Yes · **Related:** press-squash +- **Notes:** Tint toward `color.accent` on hover; revert on exit. For buttons/toolbar items. + +### `[TEMPLATE] press-squash` +- **Duration:** `anim.duration.fast` · **Curve:** `ease.elastic` · **Trigger:** Pointer down/up +- **Used By:** — · **Can Reuse:** Yes · **Related:** value-pop, panel-squash +- **Notes:** Button press feedback; reuse `value-pop` math at smaller scale. + +### `[TEMPLATE] fade-scale-in` +- **Duration:** `anim.duration.base` · **Curve:** `ease.back` · **Trigger:** Window/dialog/dropdown open +- **Used By:** — · **Can Reuse:** Yes · **Related:** praise-popup +- **Notes:** Alpha 0→1 + scale 0.85→1. Pair with scrim fade for modals. + +### `[TEMPLATE] fade-out` +- **Duration:** `anim.duration.base` · **Curve:** `ease.in` · **Trigger:** Close/dismiss +- **Used By:** — · **Can Reuse:** Yes · **Related:** fade-scale-in +- **Notes:** Alpha → 0, then deactivate/destroy. + +### `[TEMPLATE] error-shake` +- **Duration:** `anim.duration.base` · **Curve:** `ease.standard` · **Trigger:** Validation failure +- **Used By:** — · **Can Reuse:** Yes · **Related:** combo-break +- **Notes:** Small horizontal shake + `color.feedback.danger`; pair with text (a11y). + +--- + +## Effect → animation lookup + +| If you want… | Use | +| --- | --- | +| Number to tween between values | `score-count-up` | +| Emphasize an element on update | `value-pop` or **`bouncy-value-pop`** | +| Card/panel reacts to an event | `panel-squash` (+ `shadow-bounce`) or **`bouncy-hit`** | +| Streak/combo increases | `combo-pop` | +| Streak/negative feedback | `combo-break` / **`bouncy-combo-break`** / `error-shake` | +| Floating transient label/toast | `praise-popup` or **`bouncy-praise-popup`** | +| Ambient idle life | `idle-float` | +| Hover feedback | `hover-tint` / `button-hover-lift` *(template)* | +| Press feedback | `press-squash` / `button-press-squash` *(template)* | +| Open a window/dropdown | `fade-scale-in` | +| Close/dismiss | `fade-out` | diff --git a/AI/CHANGELOG.md b/AI/CHANGELOG.md new file mode 100644 index 0000000..b77fdda --- /dev/null +++ b/AI/CHANGELOG.md @@ -0,0 +1,321 @@ +# CHANGELOG + +> History of changes to the AI UI Framework (the `AI/` docs) and to notable UI components. +> Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning per [WORKFLOW.md → Versioning](./WORKFLOW.md#versioning). +> Every framework change and notable component change gets an entry here ([RULES.md](./RULES.md) R-13). + +--- + +## How to add an entry + +1. Add bullets under **[Unreleased]** in the correct category. +2. On release, move them under a new dated version heading and start a fresh `[Unreleased]`. +3. Reference the component, rule, or document affected. Link where useful. +4. For component changes, also bump the component's `Version` in [COMPONENT_INDEX.md](./COMPONENT_INDEX.md). + +**Categories:** `Added` · `Changed` · `Deprecated` · `Removed` · `Fixed` · `Security` + +**Entry template:** +``` +### [Type] — +- **Scope:** +- **What:** +- **Why:** +- **Impact:** +- **Refs:** +``` + +--- + +## [Unreleased] + +### Changed — Synthwave UI revamp: monochrome-accented dark style across all menus + +- **Scope:** framework · token · component:TitleScreen · component:SongSelect · component:ScoreHUD · component:MainMenu · animation +- **What:** Complete visual and architectural overhaul of all menu screens to match the synthwave aesthetic of the game scene. Summary of changes: + - **Style docs rewritten:** `STYLE.md`, `TOKEN_INDEX.md`, `PATTERNS.md`, `ANIMATION_INDEX.md`, and all component docs describe the new **monochrome-accented synthwave** identity (dark near-black surfaces, white text, cyan `#2ED9F2` + coral `#FF6B52` as the only two accent colors). + - **Single Menu scene:** `TitleScreen.unity` and `SongSelect.unity` merged into `Menu.unity`. The synthwave background runs continuously. Title→SongSelect is a pure UI swap — no scene load. `MenuSceneController` owns the swap. Header label fades between "TREEFORMANCE" and "SELECT SONG". + - **World-space BST tree (title screen):** 3D world-space nodes via `TreeNodeView` / `TreeLayoutManager`. Generic level-stack (`MenuTreeController`, `MenuTreeNavigator`) driven by a single `TitleTreeState` state regardless of depth. Any node can have `SubTreeRoot` for nested sub-menus. + - **Style1Palette updated:** new `Background`, `PanelFill` (dark), `AccentLight/Dark`, `AccentWarmLight/Dark`, `DiffEasy/Normal/Hard/Expert/ExpertPlus` (+ Light/Dark variants), `TextDisabled`. All hardcoded `new Color(...)` in menu components migrated to palette members. + - **BPM-sync background:** `MenuBeatTimer` drives `SynthwaveBackgroundController._beatPulse` at the hovered song's BPM during preview. `SynthwaveBackgroundController` now subscribes to both `TreeRhythmController.OnBeat` (game scene) and `MenuBeatTimer.OnBeat` (menu scene). + - **Color cycling:** `SynthwaveBackgroundController._enableColorCycle = true` in Menu scene only; sky hue PingPong 220°→320° over `_colorCyclePeriod` (default 60s). + - **Dark style applied to:** `SongCardView` (dark fill, cyan overlay, white text), `DifficultySelectView`, `TransitionScreenController`, `SongSelectLayoutBuilder`, `ScoreHUDLayoutBuilder`, `ResultScreenLayoutBuilder`. + - **New animations documented:** `tree-node-enter`, `tree-node-exit`, `tree-cursor-move`, `tree-node-confirm`, `header-label-swap`, `menu-section-fade`, `background-color-cycle`, `menu-beat-pulse` in `ANIMATION_INDEX.md`. + - **New animation tokens in TOKEN_INDEX:** `anim.duration.tree.node.in`, `anim.duration.tree.node.out`, `anim.duration.tree.stagger`, `anim.duration.header.swap`, `anim.duration.subtree.overlap`. + - **World-Space Tree Navigation pattern added** to `PATTERNS.md`. + - **Build Settings updated:** index 0 = `Menu.unity`, index 1 = `GameScene.unity`. +- **Why:** Game scene achieved a strong monochrome-accented synthwave aesthetic; menus were inconsistent (light white/gold neo-brutalist palette). User requested full revamp to match the game scene everywhere. +- **Impact:** All menu screens, all palette consumers, all AI doc readers. Old `TitleScreen.unity` and `SongSelect.unity` deleted. Components bumped: TitleScreen→0.2.0, SongSelect→0.3.0, ScoreHUD→1.2.0, MainMenu→0.1.0 (new). +- **Refs:** `AI/STYLE.md`, `AI/TOKEN_INDEX.md`, `AI/PATTERNS.md`, `AI/ANIMATION_INDEX.md`, `AI/components/TitleScreen.md`, `AI/components/SongSelect.md`, `AI/components/ScoreHUD.md`, `AI/components/MainMenu.md`, `Assets/UI/Style1/Style1Palette.cs`, `Assets/Scripts/SynthwaveBackgroundController.cs`, `Assets/Menu/MenuBeatTimer.cs`, `Assets/Menu/MenuSceneController.cs`, `Assets/Menu/TitleScreen/MenuTreeController.cs`, `Assets/Scenes/Menu.unity` + +### Added — `MarqueeLabel` primitive + marquee-scroll animation +- **Scope:** component:SongSelect · animation · shared primitive +- **What:** New `MarqueeLabel` component (`Assets/Menu/SongSelect/MarqueeLabel.cs`) — `[RequireComponent(RectMask2D)]` container that auto-sizes a TMP child label to fit, then ping-pong scrolls when text overflows at `fontSizeMin`. New `marquee-scroll` entry in `ANIMATION_INDEX`. Registered in `COMPONENT_INDEX` shared primitives table. +- **Why:** Song card titles and author names can be long; needed a graceful overflow pattern that avoids truncation and stays readable. +- **Impact:** `SongCardView` updated from raw `TMP_Text` labels to `MarqueeLabel` containers (TitleMarquee, AuthorMarquee, AlbumMarquee). `SongSelect` component bumped to `0.2.0`. +- **Refs:** `Assets/Menu/SongSelect/MarqueeLabel.cs`, `SongCardView.cs`, `AI/ANIMATION_INDEX.md`, `AI/COMPONENT_INDEX.md`, `AI/components/SongSelect.md` + +### Fixed — Carousel card sizing: center-point anchor pitfall documented +- **Scope:** framework · component:SongSelect +- **What:** Added a row to the WORKFLOW.md "Known failure modes" table: stretch anchors (0,0→1,1) make `sizeDelta` relative to parent — carousel cards must use center-point anchors (0.5,0.5) for `sizeDelta` to equal absolute pixel size. +- **Why:** Cards appeared tiny or filled the parent when `sizeDelta` was set on stretch-anchored RectTransforms. +- **Refs:** `AI/WORKFLOW.md → Known failure modes`, `SongSelectController.cs` + +### Fixed — Difficulty colors on light backgrounds: Popup vs. Panel rule documented +- **Scope:** token · component:SongSelect +- **What:** Added `color.feedback.panel.*` token rows to TOKEN_INDEX with a callout rule: use `*Panel` dark variants (not `*Popup` neon-bright) when difficulty colors appear on white/light surfaces. Updated `SongSelect.md` stylistic decisions. +- **Why:** TransitionScreenController originally used Popup colors against a white banner, making them illegible. +- **Refs:** `AI/TOKEN_INDEX.md §3`, `AI/components/SongSelect.md → Stylistic decisions`, `TransitionScreenController.cs` + +### Fixed — `Style1Typography.Apply` contract documented; Caption role flagged as unimplemented +- **Scope:** framework · style +- **What:** Added explicit rule to STYLE.md §1: `Apply` sets font/size/style/material only — `alignment`, `enableAutoSizing`, `overflowMode`, `textWrappingMode` must be set after. Marked `Caption` role as not yet in `Style1Typography.Role`; use `Label` instead. +- **Why:** Using `Role.Caption` caused compile errors; not setting `enableAutoSizing` after `Apply` silently disabled auto-sizing. +- **Refs:** `AI/STYLE.md §1` + +### Changed — Docs: explicit Unity access paths for components +- **Scope:** framework +- **What:** `INDEX`, `README`, `COMPONENT_INDEX`, `components/README`, and `_TEMPLATE` now explicitly state that components can be accessed live in Unity via **`Rhythm → Create … Demo Scene`** and/or the **UI Component Gallery board** — not only by reading per-component docs and source files. +- **Why:** Agents and humans should know both entry points when verifying or previewing components. +- **Refs:** `AI/INDEX.md`, `AI/README.md`, `AI/COMPONENT_INDEX.md`, `AI/components/README.md`, `AI/components/_TEMPLATE.md` + +### Changed — Docs: live access gate mandatory when creating components +- **Scope:** framework +- **What:** Creation workflow now requires **both** live access paths before handoff: demo scene (`Rhythm → Create … Demo Scene`) **and** gallery board (`[UIGalleryComponent]`). New **Live access gate** section in `WORKFLOW.md`; upgraded to **BLOCKER** in `REVIEW_CHECKLIST.md`; mirrored in `PATTERNS`, `COMMANDS`, `_TEMPLATE`, `components/README`, `INDEX`, `.cursor/rules/ui-framework.mdc`. +- **Why:** New components must be reachable the same way as existing ones — not docs-only. +- **Refs:** `AI/WORKFLOW.md#live-access-gate-mandatory-when-creating-a-component`, `AI/REVIEW_CHECKLIST.md`, `AI/PATTERNS.md`, `AI/COMMANDS.md` + +### Fixed — UI Component Gallery: maximize (+) clicks on carousel +- **Scope:** component:UIComponentGallery +- **What:** Maximize label is now **+** (compact). Cell header renders above preview content so nested scroll UIs (carousel) no longer steal the click. Overlay parents to the root canvas so the modal is not clipped/blocked. +- **Why:** User could not expand carousel; `[ + ]` label was awkward. +- **Refs:** `UIComponentGalleryLayoutBuilder.CreateCell`, `CreateMaximizeOverlay`, `UIComponentGalleryController.OpenMaximized` + +### Changed — UI Component Gallery: category section headers restored +- **Scope:** component:UIComponentGallery +- **What:** Board content is grouped again under labeled sections (BUTTONS, MENUS, HUD, …); each section has its own 6-column grid. Cell headers show component name only; filter tabs hide/show whole sections. +- **Why:** User preferred the original categorized layout over a flat grid with category tags on each cell. +- **Refs:** `UIComponentGalleryLayoutBuilder` (`CreateCategorySection`), `UIComponentGalleryController` (`_sections`, `Populate`) + +### Changed — UI Component Gallery: demo previews + 6-column grid +- **Scope:** component:UIComponentGallery +- **What:** Gallery cells now run **`IUIGalleryPreview`** — Score HUD shows live score/combo (12,840 · x24) with idle float + periodic hits in Play; Song Carousel auto-advances; Main Menu shows full card with idle bob. Board is a **single 6-column grid** (left-to-right, wrap); new `[UIGalleryComponent]` entries auto-append. Filter tabs hide/show cells by category. +- **Why:** Previews looked empty (e.g. Score HUD showed only chrome); user wanted demo-like scenes and a 6-wide row layout. +- **Refs:** `UIGalleryPreview.cs`, `UIGalleryPreviewUtil.cs`, `IUIGalleryPreview` on all tagged controllers + +### Changed — UI Component Gallery: both-axis scroll + maximize popup +- **Scope:** component:UIComponentGallery +- **What:** Board now scrolls **horizontally and vertically** with scrollbars (fixed 4-column grids per category, `ContentSizeFitter` both axes). Each cell has a `[ + ]` **maximize** button that opens a full-screen modal with a large, live instance of the component (CLOSE button + click-backdrop-to-close). Auto-build deferred (`Start` in Play, `EditorApplication.delayCall` in Edit) to avoid `LayoutRebuilder`-during-`Awake`/`OnValidate` errors when hosting nested controllers. +- **Why:** User wanted to scroll the whole board freely and pop a single element out to inspect it bigger. +- **Refs:** `UIComponentGalleryController` (`OpenMaximized`/`CloseMaximized`, `ScheduleEditorEnsure`), `UIComponentGalleryLayoutBuilder` (`CreateScrollbar`, `CreateMaximizeOverlay`, `CreateButton`) + +### Added — UI Component Gallery (board) + R-37 (framework + tool) +- **Scope:** component:UIComponentGallery, framework +- **What:** New **UI Component Gallery** — a live board that auto-discovers every component tagged `[UIGalleryComponent]` and renders a real, editable instance per component grouped into category sections (Buttons / Menus / HUD / Panels / Lists / Other) with filter tabs. New files under `Assets/UI/Style1/ComponentGallery/` (`UIGalleryComponent` attribute+enum, `UIComponentGalleryController`, `UIComponentGalleryLayoutBuilder`, `Editor/UIComponentGalleryEditorTools`). New **R-37** ("every component registers on the gallery"); `Style1Button`, `MainMenuController`, `SongCarouselController`, `ScoreHUDController` tagged. Menus: `Rhythm → Setup UI Component Gallery`, `Rhythm → Create UI Component Gallery Scene`. +- **Why:** User wanted one page/board to see every UI component in one place, organized by type, and edit them live. +- **Impact:** New "see all components" workflow layer; new components must add the attribute (R-37). Docs updated: `INDEX`, `RULES` (R-37), `WORKFLOW` (UI Component Gallery section + checklist), `REVIEW_CHECKLIST`, `PATTERNS`, `COMMANDS`, `_TEMPLATE`, `components/README`, `COMPONENT_INDEX`, `.cursor/rules/ui-framework.mdc`, new `components/ComponentGallery.md`. +- **Refs:** `Assets/UI/Style1/ComponentGallery/`, `AI/components/ComponentGallery.md`, `AI/RULES.md` R-37, `AI/WORKFLOW.md#ui-component-gallery-board-r-37` + +### Added — R-36 Edit-mode visibility & saveable setup (framework) +- **Scope:** framework +- **What:** New **R-36** in `RULES.md`; `WORKFLOW.md` section *Edit-mode visibility & saveable setup*; INDEX router row; `REVIEW_CHECKLIST` §12 blockers; `_TEMPLATE.md` / `components/README.md` updated. Canonical refs: `MainMenuSceneBuilder`, `SongCarouselEditorTools`, `SongCarouselDemoSceneBuilder`. +- **Why:** Agents shipped procedural UI only at Play (`Awake`-only demo setup); Scene view empty; `Rhythm → Setup` failed first time; scenes not saveable. +- **Refs:** `AI/RULES.md` R-36, `AI/WORKFLOW.md#edit-mode-visibility--saveable-setup-r-36` + +### Added — Song Carousel v1.0.0 +- **Scope:** component:SongCarousel +- **What:** `SongCarouselController` — horizontal Style 1 carousel with drag snap, prev/next `Style1Button` arrows, squishy card selection, demo scene + `Rhythm → Setup Song Carousel` / `Rhythm → Create Song Carousel Demo Scene`. +- **Why:** User-requested song picker UI following Style 1 patterns. +- **Refs:** `Assets/UI/Style1/SongCarousel/`, `AI/components/SongCarousel.md` + +### Fixed — Song Carousel edit-mode visibility + first-time setup +- **Scope:** component:SongCarousel +- **What:** Scene/demo builders now call `RebuildSongCarouselLayout()` before save; `Rhythm → Setup Song Carousel` creates a carousel on Canvas if missing; `OnEnable` builds in Edit mode; scene marked dirty on rebuild. +- **Why:** UI only appeared at Play (runtime `Awake`), so Scene view was empty and changes were not saveable. +- **Refs:** `SongCarouselController`, `SongCarouselEditorTools`, `SongCarouselDemoSceneBuilder` + +### Fixed — Song Carousel card layout / clipping +- **Scope:** component:SongCarousel +- **What:** Restructured track as `[Prev][Viewport][Next]` row; card shadows clipped per-card; reduced selection scale; corrected scroll centering with content padding; auto-rebuild when layout structure changes. +- **Why:** Cards overlapped arrows, shadows bled outside mask, and snap math mis-centered cards. +- **Refs:** `SongCarouselLayoutBuilder`, `SongCarouselCard`, `SongCarouselController` + +### Changed — Rhythm menu bar explicit in workflow (R-17) +- **Scope:** framework +- **What:** New **Rhythm menu bar (mandatory)** section in `WORKFLOW.md`; R-17/R-18 strengthened; `_TEMPLATE.md`, `INDEX.md`, `.cursor/rules/ui-framework.mdc`, `MainMenu.md` updated to require all UI setup under **`Rhythm → …`** Unity top menu. +- **Why:** Component setup must be explicitly discoverable — not scattered across Window/Assets menus. +- **Refs:** `AI/WORKFLOW.md#rhythm-menu-bar-mandatory-r-17`, `AI/RULES.md` R-17 + +### Added — Main Menu v1.0.0 (rebuilt via workflow) +- **Scope:** component:MainMenu, primitive:Style1Button +- **What:** `MainMenuController` with Play/Songs/Settings/Credits `Style1Button` nav, ASCII bold typography, sub-panels, intro + idle float. `ApplySquishyNavPreset` / `ApplyPrimaryNavStyle` on `Style1Button`. Editor menus + demo scene builders restored. +- **Why:** User-requested rebuild following AI UI workflow after prior removal. +- **Refs:** `Assets/UI/Style1/MainMenu/`, `AI/components/MainMenu.md` + +### Removed — Main Menu implementation (user rebuild via workflow) +- **Scope:** component:MainMenu +- **What:** Deleted `Assets/UI/Style1/MainMenu/` (controller, layout builder, editor tools, demo), `MainMenu.unity`, `MainMenuDemo.unity`. Removed scenes from Build Settings. `MainMenu.md` kept as **Removed** stub with rebuild guide (R-04). +- **Why:** User requested clean slate to rebuild using AI workflow. +- **Impact:** `Style1Button` primitive retained. `Rhythm → Setup Main Menu` / scene builders gone until rebuilt. +- **Refs:** `AI/components/MainMenu.md`, `AI/INDEX.md`, `AI/COMPONENT_INDEX.md` + +### Fixed — Procedural sprites baked to a persistent asset (R-35) +- **Scope:** framework / shared:`Style1Sprites` +- **What:** `Style1Sprites` now loads a baked 9-slice asset (`Assets/UI/Style1/Resources/Style1RoundedRect.png`) generated by new `Style1SpriteBaker` (menu **Rhythm → Bake Style 1 Sprites**, auto-bakes on load when missing). A single white sprite is tinted per-Image via `Image.color`; runtime `Sprite.Create` kept only as fallback. +- **Why:** Runtime-only sprites never serialize → panels showed **square in Scene view, rounded only in Play** and edits didn't persist. A real asset serializes, so Scene == Game and the result is WYSIWYG/editable. +- **Impact:** All Style 1 panels/buttons (Score HUD, Main Menu, Style1Button). Re-bake + resave scenes to store the asset GUID. `WhiteRounded`/`BlackRounded` API unchanged (both return the baked sprite). +- **Refs:** `Assets/UI/Style1/Style1Sprites.cs`, `Assets/UI/Style1/Editor/Style1SpriteBaker.cs`, `AI/WORKFLOW.md#procedural-sprites-checklist-r-32` + +### Added — Interactive UI rule (R-34) +- **Scope:** framework +- **What:** `UIEventSystemUtil`, `Style1ButtonInput` raycast forwarder, ExecuteAlways edit-vs-play split. WORKFLOW Interactive UI checklist, INDEX router, REVIEW_CHECKLIST, PATTERNS, component docs. +- **Why:** Menu animations dead: missing InputSystemUIInputModule, raycast on wrong node, OnEnable resetting tweens. +- **Refs:** `AI/WORKFLOW.md#interactive-ui-checklist-r-34`, `AI/RULES.md` R-34 + +### Fixed — Style1Button CS0104 Object ambiguity +- **What:** `Object.DestroyImmediate` → `UnityEngine.Object.DestroyImmediate` when `using System` is present. +- **Refs:** `Style1Button.cs` line 198 + +### Fixed — Style1Button PrimeTween compile errors +- **Scope:** component:Style1Button +- **What:** `Tween.Scale` used invalid start+end overload; `Tween.Custom` with `Color` replaced with float lerp pattern. Documented PrimeTween traps in R-29, new R-33, WORKFLOW checklist. +- **Refs:** `Style1Button.cs`, `AI/WORKFLOW.md#primetween-compile-checklist-r-29-r-33` + +### Added — Style 1 Button + Main Menu v2 +- **Scope:** component:Style1Button, component:MainMenu +- **What:** `Style1Button` primitive — thick `Role.Button` typography, hover lift, press squash/translate, elastic release. Main Menu upgraded: Play/Song/Menu/Credits/Quit with `Style1Button`, Song panel, Panel Colors, R-32 layout refresh. +- **Refs:** `Assets/UI/Style1/Style1Button.cs`, `AI/components/Style1Button.md`, `AI/components/MainMenu.md` + +### Added — Procedural sprite refresh & theme colors (R-32) +- **Scope:** framework, component:ScoreHUD +- **What:** `Style1Sprites` do not serialize to scene YAML. Controllers need `[ExecuteAlways]`, `OnEnable` → `EnsureStyle1Layout()`, `RefreshProceduralSprites()`, `ApplyThemeColors()`, Panel Colors on controller, `RebuildStyle1Layout()` for editor. Agent procedure in WORKFLOW + ScoreHUD doc. +- **Why:** GameScene showed square flat HUD after reload; users editing child Image colors saw no change on Play. +- **Refs:** `AI/RULES.md` R-32, `AI/WORKFLOW.md#procedural-sprites-checklist-r-32`, `ScoreHUDController.cs` v1.1.0 + +### Added — Editor layout & Inspector rules (R-30, R-31) +- **Scope:** framework +- **What:** `OnValidate()` must rebuild invalid layout in Edit mode (square Scene-view corners). Editor HelpBox must document controller-field vs child-hierarchy editing. `*LayoutBuilder` must preserve `CreateLabel` overloads (compile trap). Extended WORKFLOW, RULES, REVIEW_CHECKLIST §12, PATTERNS, ScoreHUD doc. +- **Why:** Repeat incidents: broken `MainMenuLayoutBuilder.CreateLabel` blocked compile; stale sprites only fixed on Play; users editing child hierarchy thought Inspector "didn't work." +- **Refs:** `AI/RULES.md` R-30–R-31, `AI/WORKFLOW.md` + +### Removed — Score HUD Bouncy & Style 1 Button (user recreation) +- **Scope:** component:ScoreHUDBouncy, component:Style1Button +- **What:** Deleted `Assets/UI/Style1/ScoreHUDBouncy/`, `ScoreHUDBouncyDemo.unity`, `Style1Button.cs`, and per-component docs. Main Menu reverted to placeholder `UnityEngine.UI.Button` nav items (v1.2.0). +- **Why:** User will recreate button (and optionally bouncy HUD) using the AI workflow from scratch. +- **Recreate:** [examples/CreateMeterButton.md](./examples/CreateMeterButton.md) · [WORKFLOW.md → Creating Variants](./WORKFLOW.md#creating-variants) for HUD variant. + +### Added — Runtime layout & wiring rules (R-25–R-29) +- **Scope:** framework +- **What:** New blocker/standard rules and a mandatory [WORKFLOW.md → Runtime layout & wiring](./WORKFLOW.md#runtime-layout--wiring-mandatory) section documenting `DestroyImmediate`, `InvalidateCachedReferences`, deep `IsLayoutValid`, `Start()` wiring, and compile-check requirements. Updated PATTERNS blueprint, REVIEW_CHECKLIST §12, INDEX router, COMMANDS, Cursor rule, ScoreHUD reference doc. +- **Why:** Prevent recurrence of square panels, dead buttons, score-stuck-at-0, and missing-`using` compile errors from layout rebuild races. +- **Refs:** `AI/RULES.md`, `AI/WORKFLOW.md`, `AI/PATTERNS.md`, `AI/REVIEW_CHECKLIST.md`, `.cursor/rules/ui-framework.mdc` + +### Added — Style 1 Button primitive +- **Scope:** component:Style1Button +- **What:** `Assets/UI/Style1/Style1Button.cs` — neo-brutalist button with hover lift, press squash, elastic release, and accent tint. Used by Main Menu. +- **Refs:** `AI/components/Style1Button.md` + +### Changed — Main Menu uses Style 1 Button +- **Scope:** component:MainMenu +- **What:** Replaced generic `UnityEngine.UI.Button` nav items with `Style1Button`. Auto-rebuilds stale menu scenes on Play. v1.1.0. +- **Refs:** `AI/components/MainMenu.md` + +### Fixed — Score HUD score stuck at zero after runtime rebuild +- **Scope:** component:ScoreHUD +- **What:** Layout rebuild now uses `DestroyImmediate` and clears stale serialized UI refs; `TreeRhythmController` wires the HUD in `Start()` after all `Awake()` layout passes. +- **Why:** Deferred `Destroy` left duplicate hierarchies — score tweens updated invisible old text while the visible panel stayed at 0. +- **Refs:** `ScoreHUDLayoutBuilder.cs`, `ScoreHUDController.cs`, `TreeRhythmController.cs` + +### Fixed — Score HUD stale scene layout +- **Scope:** component:ScoreHUD +- **What:** `ScoreHUDController.Awake()` now validates rounded sprites on Border/AsciiBackground/Shadow and rebuilds via `ScoreHUDLayoutBuilder` when missing — fixes square/weird meter in `GameScene` after old scene data. +- **Refs:** `Assets/UI/ScoreHUDController.cs` + +### Added — Main Menu component +- **Scope:** component:MainMenu +- **What:** Style 1 main menu (`Assets/UI/Style1/MainMenu/`) with Play → GameScene, Settings/Credits in-menu panels, Quit, Inspector toggles, demo + production scene builders (`Rhythm → Create Main Menu Scene`). +- **Why:** User-requested navigation UI in the same Style 1 language as the score meter. +- **Refs:** `AI/components/MainMenu.md` + +### Added — Score HUD Bouncy variant +- **Scope:** component:ScoreHUDBouncy +- **What:** New variant at `Assets/UI/Style1/ScoreHUDBouncy/` with exaggerated squash, rotation wobble, position punch, elastic overshoot, and spinning praise popups. Original Score HUD untouched. Includes demo scene (`Rhythm → Create Score HUD Bouncy Demo Scene`) and per-component doc `AI/components/ScoreHUDBouncy.md`. +- **Why:** User-requested stronger, bouncier, distorted hit motion as an alternative to the standard HUD. +- **Refs:** `AI/components/ScoreHUDBouncy.md`, `Assets/UI/Style1/ScoreHUDBouncy/` +- **Scope:** framework +- **What:** Restructured to **one documentation file per reusable component** under `AI/components/`. Added `AI/INDEX.md` as a read-router (Task → Read set), converted `AI/COMPONENT_INDEX.md` into a thin registry that links to per-component docs, and added `AI/components/README.md` + `AI/components/_TEMPLATE.md`. Documented the reference Score HUD as `AI/components/ScoreHUD.md` (with an exact "Files" section to scope reads). +- **Why:** Per-component files scale better for humans and AI; the router + exact file lists let agents read only what's relevant instead of scanning the whole codebase. +- **Impact:** All component detail now lives in `components/.md`. New components must add a per-component doc + INDEX/COMPONENT_INDEX rows. +- **Refs:** `AI/INDEX.md`, `AI/components/`, `AI/COMPONENT_INDEX.md` + +### Added — Cursor scoped-reading rule +- **Scope:** framework +- **What:** Added `.cursor/rules/ui-framework.mdc` (`alwaysApply`) instructing agents to read `AI/INDEX.md` first, open the single matching component doc, read only its listed files, cap context (~≤4 docs / ≤6 files), and never blanket-scan `Assets/**`. +- **Why:** Keep AI context small and on-route; stop full-codebase reads on every UI task. +- **Refs:** `.cursor/rules/ui-framework.mdc`, `AI/INDEX.md` + +### Added — Worked example + sample prompt +- **Scope:** framework +- **What:** Added `AI/examples/CreateMeterButton.md` — an end-to-end "create a meter button" walkthrough (search → bash duplicate → rename → controller/builder/editor/demo → register → review) including a ready-to-paste sample prompt. +- **Why:** Give humans and AI a concrete, copy-pasteable path that demonstrates the Score HUD standard and scoped reading. +- **Refs:** `AI/examples/CreateMeterButton.md` + +--- + +## [1.0.0] — 2026-06-23 + +Initial release of the AI UI Development Framework. + +### Added — AI framework documentation system +- **Scope:** framework +- **What:** Created the `AI/` documentation system with 12 core documents: + `README.md`, `RULES.md`, `STYLE.md`, `WORKFLOW.md`, `PATTERNS.md`, `COMMANDS.md`, + `COMPONENT_INDEX.md`, `ANIMATION_INDEX.md`, `TOKEN_INDEX.md`, `DIRECTORY.md`, + `REVIEW_CHECKLIST.md`, `CHANGELOG.md`. +- **Why:** Establish a single source of truth so future AI agents and developers build UI consistently, reuse-first, and review against one standard. +- **Impact:** All future UI work must follow this framework. +- **Refs:** `AI/README.md` + +### Added — Rule set (R-01 … R-24) +- **Scope:** framework +- **What:** Codified non-negotiable rules: reuse-first, duplicate-before-modify, search-before-create, no hardcoded design values, no duplicate animations/components, the "Score HUD standard" authoring rules (Inspector-editable, live toggles, custom editor + Build button, setup menu, interactive demo + demo-scene builder, idempotent layout builder, logic/presentation separation), and stop-and-ask on ambiguity. +- **Why:** Prevent design drift and protect shared assets. +- **Refs:** `AI/RULES.md` + +### Added — Style language & design tokens (seeded from Score HUD) +- **Scope:** token / framework +- **What:** Documented the visual language (typography, color, borders, radius, shadow, motion, a11y, responsive) and a token system. Seeded **Live** tokens from the existing Score HUD (`Style1Palette`, `Style1Typography`, `Style1Sprites`, `ScoreHUDController` motion values); reserved **Template** tokens for future needs. +- **Why:** Make design values reusable and ban hardcoding (R-07, R-08). +- **Refs:** `AI/STYLE.md`, `AI/TOKEN_INDEX.md`, `Assets/UI/Style1/` + +### Added — Pattern library & component blueprint +- **Scope:** pattern / framework +- **What:** Documented 11 patterns (Buttons, Cards, Panels, Windows, Toolbars, Dialogs, Lists, Dropdowns, Tabs, Forms, Navigation) plus the mandatory six-file Component Blueprint derived from the Score HUD. +- **Why:** Ensure every new component is built from a proven blueprint and is Inspector-editable + demo-able. +- **Refs:** `AI/PATTERNS.md` + +### Added — Component & animation indexes +- **Scope:** component / animation +- **What:** Catalogued the existing Score HUD, Score HUD Demo, and shared Style 1 classes (`Style1Palette`, `Style1Typography`, `Style1Sprites`, `Style1AsciiImage`, `ScoreDisplayUtil`). Registered 8 reusable animations (`score-count-up`, `value-pop`, `panel-squash`, `shadow-bounce`, `combo-pop`, `combo-break`, `praise-popup`, `idle-float`) plus motion templates. +- **Why:** Drive reuse and make existing assets discoverable. +- **Refs:** `AI/COMPONENT_INDEX.md`, `AI/ANIMATION_INDEX.md` + +### Added — Workflows, commands, directory, review gate +- **Scope:** framework +- **What:** Step-by-step workflows for every UI task; AI commands (`/scan-project`, `/new-component`, `/modify-component`, `/review-component`, `/register-component`, `/update-index`, `/archive-component`); canonical Unity folder structure; comprehensive review checklist. +- **Why:** Make the process executable and verifiable end-to-end. +- **Refs:** `AI/WORKFLOW.md`, `AI/COMMANDS.md`, `AI/DIRECTORY.md`, `AI/REVIEW_CHECKLIST.md` + +### Reference — Score HUD adopted as the gold standard +- **Scope:** component:ScoreHUD +- **What:** Designated the existing Score HUD (`Assets/UI/`) as the reference implementation that all conventions derive from. No code changes were made to the component in this release — it was documented and indexed at version 1.0.0. +- **Why:** Anchor the framework in working, shipped code. +- **Refs:** `Assets/UI/ScoreHUDController.cs`, `Assets/UI/Style1/`, `Assets/UI/Demo/`, `Assets/Rhythm/Editor/ScoreHUDEditorTools.cs` + +--- + +## Version history + +| Version | Date | Summary | +| --- | --- | --- | +| 1.0.0 | 2026-06-23 | Initial AI UI Framework; Score HUD documented as reference | diff --git a/AI/COMMANDS.md b/AI/COMMANDS.md new file mode 100644 index 0000000..87b2eab --- /dev/null +++ b/AI/COMMANDS.md @@ -0,0 +1,201 @@ +# COMMANDS + +> Standard AI commands. Each command is a named, repeatable procedure an agent runs on request. Commands are the executable face of the [WORKFLOW.md](./WORKFLOW.md) procedures. +> Related: [WORKFLOW.md](./WORKFLOW.md) · [RULES.md](./RULES.md) · [REVIEW_CHECKLIST.md](./REVIEW_CHECKLIST.md) + +--- + +## Conventions + +- Commands are written `/command-name arg=value`. +- Every command begins by **loading [RULES.md](./RULES.md)** and ends by **updating indexes** (R-11) where applicable. +- If any step is ambiguous or risks a rule violation, **stop and ask** (R-21). +- Commands never commit to Git unless the user explicitly asks (R-23). + +Command map: + +| Command | Purpose | Backing workflow | +| --- | --- | --- | +| `/scan-project` | Search before creating | [Search](./WORKFLOW.md#the-golden-loop-applies-to-all-workflows) | +| `/new-component` | Create a new component | [Creating Components](./WORKFLOW.md#creating-components) | +| `/modify-component` | Change an existing component | [Modifying Components](./WORKFLOW.md#modifying-components) | +| `/review-component` | Run the review gate | [Reviewing Components](./WORKFLOW.md#reviewing-components) | +| `/register-component` | Add to indexes | [Registering Components](./WORKFLOW.md#registering-components) | +| `/update-index` | Sync indexes with reality | [Updating Documentation](./WORKFLOW.md#updating-documentation) | +| `/archive-component` | Deprecate/retire safely | [Deprecating Components](./WORKFLOW.md#deprecating-components) | + +--- + +## /scan-project + +**Purpose:** Search the project for anything reusable before building. Mandatory precursor to creation (R-05). + +**Args:** `query=` (e.g. "progress bar", "fade rise", "gold accent"). + +**Steps:** +1. Load [RULES.md](./RULES.md). +2. Search [COMPONENT_INDEX.md](./COMPONENT_INDEX.md) for components matching `query` (name, tags, description). +3. Search [PATTERNS.md](./PATTERNS.md) for a matching blueprint. +4. Search [ANIMATION_INDEX.md](./ANIMATION_INDEX.md) for matching motion (by effect keyword). +5. Search [TOKEN_INDEX.md](./TOKEN_INDEX.md) for existing colors/sizes/durations. +6. Search the codebase (`Assets/UI/**`, `Assets/**/Editor/**`) for related scripts. +7. **Report:** closest component, closest pattern, reusable animations/tokens, and a recommendation: *reuse as-is*, *make a variant*, or *create new*. + +**Output:** a short findings list + recommendation. Does not modify anything. + +--- + +## /new-component + +**Purpose:** Create a brand-new component **from a pattern** when no existing component is close enough. + +**Args:** `name=` `pattern=` `style=` `[data=]` + +**Steps:** +1. Load [RULES.md](./RULES.md). Run `/scan-project query=`. If a ≥~70% match exists → abort and suggest `/modify-component` or a variant (R-10). +2. Confirm the [PATTERNS.md](./PATTERNS.md) blueprint for `pattern`. +3. Create folders per [DIRECTORY.md](./DIRECTORY.md) (`Assets/UI/