TURNCRAFT/docs/GLOWUP_E_handoff.md
jing 9c668d340c Headshell Workshop + Glow-Up phase: assembly minigame, art pass, review fixes
- 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>
2026-07-14 21:32:07 +10:00

125 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 14` 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` + `0112` 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.