Custom-GLB drop-in system: manifest/registry with procedural fallbacks, IndexedDB override layer for zero-deploy playtesting, and a three-panel in-browser fitting editor. Physics/visual decoupling makes every mesh swappable; blob.body is the one paintable special case (UV requirements). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.6 KiB
BLOBBO Workshop — custom assets + in-game editor (plan, 2026-07-18)
Goal: John designs/builds models (Blender, or farm-generated GLB) and drops them into the live game without touching code — plus an in-browser editor to preview, fit, and export the mapping.
Why this is easy here
Physics and visuals are fully decoupled: every collider is a primitive; every
mesh is cosmetic. Swapping a mesh can never break gameplay. The ONE special
case is the blobbo body — the paint system stamps into a canvas texture through
the mesh's UVs — so a custom blob needs clean, non-overlapping UVs and its
material's map slot handed to PaintSkin.
Reskinnable slots (the inventory)
| Slot id | Today | Notes |
|---|---|---|
blob.body |
UV sphere | PAINTABLE — needs clean UVs; SkinnedMesh OK (idle/wobble clip plays via mixer; squash still applies at group level) |
blob.face |
procedural googly eyes | separate from paintable body, by design |
ghost.body |
translucent blob copy | auto-derived from blob.body (desaturated) |
cannon.base / cannon.barrel |
cylinders | per-colour tint applied on top |
machine.plate |
box + base | pressure plate |
machine.boot |
boot+spring primitive | farm GLB already exists (assets/meshes/prop-spring-boot.glb) |
machine.bucket |
cylinder shell + fill | farm GLB exists (prop-paint-bucket.glb) |
machine.arch |
frame + bubbles | bubble cleanser |
machine.belt |
striped box | conveyor |
course.scenery.* |
giant boxes (cereal box etc.) | free-place decorative slots; toaster GLB exists |
course.tramp |
orange pad | gap launcher |
course.tunnel |
slab + posts | MINI tunnel |
course.finish |
pink podium | finish pad |
fx.puddle |
flat glossy slab | material/decal upgrade slot |
| UI: title wordmark, HUD | CSS/DOM | swap via CSS/vars, out of scope for v1 |
Architecture (two lanes + integration)
Lane I — Asset runtime (src/assets/)
assets/manifest.json maps slot → {url, offset, rotation, scale, options}.
AssetRegistry (GLTFLoader + cache) resolves slots; every construction site
falls back to today's procedural primitive when a slot is empty or fails to
load — an empty manifest must produce today's game, byte-for-byte behavior.
Construction sites (createBlob, cannon barrel, machine parts, greybox scenery)
ask the registry instead of building directly, via a tiny slotMesh(world, 'machine.boot', buildProcedural) hook. Blob slot additionally: UV sanity check
(warn if overlapping/absent), PaintSkin adoption of the delivered material, and
optional AnimationMixer for a named idle clip. Local override layer:
manifest + GLB blobs can live in IndexedDB (set by the editor) and take
precedence — so custom assets are playtestable on the LIVE site with zero deploys.
Lane J — Workshop editor (/editor.html, src/editor/)
A separate page sharing the game's modules. Three panels:
- Slots — every slot with live thumbnail; click to select.
- Stage — the actual game world (greybox + machines idling) rendering the current assets; orbit camera; selected slot highlighted.
- Fit — drag-drop a
.glbfrom disk onto a slot → instant swap in the stage; sliders/inputs for offset/rotation/scale; paintability report for blob.body (UV coverage, tri count, material count); "Test drive" button boots the REAL game in-page with overrides active. Export: ⬇manifest.jsondownload + "Save locally" (IndexedDB override, with a persistent "custom assets active — clear?" pill in the game). No server writes: committing an asset pack = John drops the GLB inassets/live/+ manifest in the repo (documented in the panel's "ship it" help text).
Integration (main session)
Wire registry into game.ts construction, ship /blobbo/editor.html, verify
(empty-manifest parity, toaster GLB in a scenery slot, blob swap with the farm
mesh incl. paint), deploy. Ship the 4 existing farm GLBs as the first pack.
Blender/authoring conventions (put in the editor's help panel too)
- Y-up, -Z forward, meters; blob body ≈ 1.0u diameter, origin at CENTER; props origin at ground-contact center. Single material preferred.
- Paintable blob: one UV island set, no overlaps, no mirrored UVs.
- Rigged: single armature, clips named
idle(loop) and optionallyroll; keep ≤ ~40 bones (mobile later). GLB embedded textures ≤2048². - Licensing per asset-pipeline skill: 🟢 web-ok only (farm-generated = ok).
Out of scope v1 (candidate wave 4)
Course layout editing (move/add machines, puddles, boxes → course JSON), animation retarget beyond idle clips, multi-pack management, shared packs.