- Workshop (WORKSHOP_CARTRIDGE): five-stage cartridge assembly at Deck A — seat/square, crimp four tag-wires, torque screws, ride-the-arm counterweight balance, needle-drop diagnostic with per-fault audio + scope. Relay-synced (per-field co-op merge: held screw + carried wire survive remote state). - Glow-Up (G1-G5): 32px atlas with per-voxel variants, selective LED bloom (quality-gated), screen-print decal system + party flyers, mixer/PCB worldgen density pass, record groove-sheen side texture. - 10 confirmed multi-agent review fixes, incl. co-op screw-stomp soft-lock, ride-snap collider-identity (magnet feet / eaten record-fling), workshop SFX exact-match map (rca_seated hijack), beam ride colliders to the head, double-crimp guard, WIRING INCOMPLETE diagnosis mode, skate-abort timer, completedState wiring, per-tick material churn, trackingHeavy platter drag. - Crossfader playtest fix: slew-limited sled (3.4 v/s) + ribbed grip caps with amber index — the sled reads as a heavy handle, not a teleporting wall. - Demo harnesses: machinesDemo hold-key wiring, playerDemo seesaw phase continuity, audioDemo incomplete fault button. - Workshop sync: exact 1.0 screw endpoint gets its own emit signature. Verified: typecheck + vite build clean, live solo quest smoke, two-client co-op relay smoke (simultaneous torque, no rewind, exact convergence). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
125 lines
6.5 KiB
Markdown
125 lines
6.5 KiB
Markdown
# Glow-Up (Lane E / fx) — Handoff
|
||
|
||
**Brief:** [docs/briefs/GLOWUP_ART.md](briefs/GLOWUP_ART.md)
|
||
**Scope done here:** **G3 (screen-print decals)** and **G5 (record side texture)** —
|
||
the two `src/fx/**`-owned tasks. G1/G2 shipped in
|
||
[GLOWUP_A_handoff.md](GLOWUP_A_handoff.md); G4 in
|
||
[src/worldgen/HANDOFF.md](../src/worldgen/HANDOFF.md).
|
||
**Status:** ✅ G3 complete, browser-verified in the real game (port 5212),
|
||
typecheck clean, zero console errors. **G5 texture generator complete; its
|
||
platter wiring is left for Lane D** (this lane does not edit `platter.ts`).
|
||
|
||
---
|
||
|
||
## What shipped
|
||
|
||
### G3 — screen-print decal system ([src/fx/decals.ts](../src/fx/decals.ts), new)
|
||
|
||
A `DecalSet` that bakes text/markings onto `CanvasTexture`s and applies them to
|
||
thin plane meshes floating `0.05` proud of the gear faces, with `polygonOffset`
|
||
(`factor/units = -4`) so there is **no z-fighting** even at grazing angles.
|
||
One canvas per gear piece → **13 plane meshes total** (< the brief's 25
|
||
draw-call budget; measured live via `window.TURNCRAFT.decals`).
|
||
|
||
All positions derive from `LAYOUT` (`src/core/constants.ts`) and the worldgen
|
||
anchors (`MIXER`, `DECK_A`, `DECK_B`, `PATCH`, `UNDER` from
|
||
`src/worldgen/anchors.ts`) — **nothing hardcoded**, so a booth-layout change
|
||
moves the print with it.
|
||
|
||
Print set (all browser-confirmed legible at play distance):
|
||
- **Mixer face:** `CH 1–4` ahead of each fader alley, a tick ladder down each
|
||
alley, the `TURNCRAFT-800` wordmark, and crossfader `A ↔ B` (A on the deck-A
|
||
side).
|
||
- **Each deck:** `START·STOP`, `33`/`45`, a pitch `+/−` scale ladder, and a
|
||
"Quartz Direct Drive" script along the plinth front. Placed on the plinth
|
||
ring/corners, clear of the platter radius (no clipping with the spinning
|
||
record — verified at 33).
|
||
- **Patch bay:** `PATCH BAY` + `01–12` socket numbers aligned to the grid (on
|
||
the alu panel face, `backWallZ − 2`, not the raw wall behind it).
|
||
- **Fuse box:** `FUSE 250V` legend.
|
||
- **Four procedural party flyers** (word-bank names, one accent colour + border
|
||
each): two flanking the patch bay on the bare back wall, two on the side
|
||
walls near the front lip.
|
||
|
||
Orientation detail: on flat (`up`) faces the plane's canvas-up points to the
|
||
booth front, so each glyph is flipped 180° **in place** (letterforms only —
|
||
positions and tick marks stay put) to read from the player's front-edge view.
|
||
|
||
### G5 — record side texture (`recordSideTexture()` in the same file)
|
||
|
||
A fine light/dark groove-ring `CanvasTexture` for the vinyl tier **side**
|
||
cylinders (rings horizontal, `RepeatWrapping`, `NearestFilter`). Standalone
|
||
generator, no side effects. **Left for Lane D to wire into `platter.ts`** —
|
||
exact snippet in [src/fx/HANDOFF.md](../src/fx/HANDOFF.md) (Glow-Up section).
|
||
|
||
## Files touched
|
||
|
||
| file | task | note |
|
||
|---|---|---|
|
||
| `src/fx/decals.ts` | G3+G5 | **new** — `DecalSet`, `recordSideTexture()` |
|
||
| `src/main.ts` | merge | additive: build `DecalSet`, add `.group` to scene, dev handle |
|
||
| `src/fx/HANDOFF.md` | docs | API + the `recordSideTexture()` wiring snippet for Lane D |
|
||
|
||
**Merge points (per the brief):**
|
||
- `src/main.ts` — shared with the Workshop + Glow-Up-A briefs. My edits are 3
|
||
disjoint additive lines (import, `new DecalSet()` after the machines block,
|
||
and `decals` on the `window.TURNCRAFT` handle).
|
||
- `src/worldgen/buildBooth.ts` — listed as a merge point, but **not needed**:
|
||
G3 reads existing anchors rather than adding worldgen dressing, so buildBooth
|
||
is untouched.
|
||
|
||
## Verification (real game, port 5212)
|
||
|
||
- `npm run typecheck` — **clean** (exit 0), whole tree.
|
||
- Cine screenshots (`window.TURNCRAFT_CINE`): mixer face, deck top, patch bay,
|
||
side-wall flyer, and a grazing pass across the mixer — every label legible and
|
||
correctly oriented, **no z-fighting**, and **zero console errors**.
|
||
- Draw calls: `window.TURNCRAFT.decals` → **13** meshes (< 25). Also **logged at
|
||
runtime** in the `DecalSet` constructor: `[turncraft] screen-print decals: 13
|
||
draw calls (budget < 25)`.
|
||
- Confirmed the decals are additive: toggling `decals.group.visible` removes
|
||
only the labels/flyers; the floating `+` shapes near the patch bay are the
|
||
pre-existing RCA cable plugs (Lane C), not decals.
|
||
- **No quest regression:** decals live in `decals.group` (a `MeshBasicMaterial`
|
||
plane group) and add **zero** physics colliders (`machines.getColliders()`
|
||
stays 58); interaction is voxel-DDA raycast, not scene-mesh raycast, so the
|
||
decal planes cannot intercept use/mine rays. Booth build unchanged: **746 ms,
|
||
467 chunk meshes** (< 600), deterministic (anchors untouched).
|
||
- **fps:** synchronous per-frame render timing (rAF is throttled in the preview
|
||
pane) at the mixer, retina buffer: bloom-off ≈ 440 fps, bloom-on ≈ same order
|
||
— decals (13 static planes) add no measurable regression; comfortably > 100.
|
||
- Sits cleanly alongside G1 (atlas variants), G2 (LED bloom), G4 (dense knobs).
|
||
|
||
### Before/after screenshots (`docs/progress-cutoff/`)
|
||
|
||
Captured via `window.TURNCRAFT_CINE` in the real game (port 5205):
|
||
`mixer_before.jpg` / `mixer_after.jpg` (flagship before/after), `deck_top_after.jpg`
|
||
(Deck A — `START·STOP` + plinth script, clear of the platter), `pcb_fuse_after.jpg`
|
||
(`FUSE 250V` legend over the PCB-trace floor), `fullbooth_win.jpg` (emissive-lifted
|
||
"living booth" — decks, mixer labels + glowing alley pips, patch wall + flyers).
|
||
|
||
## G5 texture fix (post-merge regression)
|
||
|
||
Lane D found the merged `recordSideTexture()` had a **dark base** (`#101013`),
|
||
which as a multiply `map` blacked out the vinyl (Deck A side measured
|
||
`~[38,66,152] → ~[10,8,8]`). Contradicted this doc's "near-white base" intent —
|
||
the other writer's dark version had won the merge. **Fixed:** inverted to a
|
||
near-white base (`0.97`) with faint dark groove lands (`0.60`), a soft shoulder
|
||
(`0.80`) and a bright sheen lip (`1.0`), 16 rings/tile — neutral greys so the
|
||
multiply never shifts hue. Re-verified live via `readPixels` on the actual Deck A
|
||
record side (map applied to `sideMat` at runtime, then reverted): blue channel
|
||
`41 → 36` (~12% dip, stays clearly blue) vs an all-black test map's `41 → 17`
|
||
blackout. Signature preserved; rings read as subtle sheen.
|
||
|
||
## Not done / left for others
|
||
|
||
- **G5 platter wiring** — Lane D applies `recordSideTexture()` to the tier-side
|
||
material in `platter.ts` (snippet in `src/fx/HANDOFF.md`); now safe to wire.
|
||
|
||
## Note — concurrent edits
|
||
|
||
`src/fx/decals.ts` was refined by another writer mid-session (patch-panel face
|
||
offset `backWallZ − 2`; flyer wall anchors via `rimThickness`/`WORLD_X`). Those
|
||
changes are correct and were kept; the browser verification above reflects the
|
||
merged file.
|