Skip to content

[feat] 30-author-kit: what a game def can say — primitives, lights, materials, flags, custom skies, true-look cards - #240

Open
AlexZ005 wants to merge 4 commits into
release/nextfrom
feat/30-author-kit
Open

AlexZ005 wants to merge 4 commits into
release/nextfrom
feat/30-author-kit

Conversation

@AlexZ005

Copy link
Copy Markdown
Collaborator

Roadmap 30 lane 30-author-kit (fork 10): the template builder (scripts/author-templates.cjs) grows what a finished-looking game def needs. Two lanes build on this branch (30-visuals-mod, 30-visuals-core).

What landed (one commit per phase)

  • P0 — primitives, lights, materials, flags (10e71fd): capsule, plane, ring, icosahedron, dodecahedron, box bevel (a port of three/examples RoundedBoxGeometry, baked into a plain BufferGeometry, because ObjectLoader cannot rebuild the subclass type); light kinds spot / directional (shadow frustum fitted to the built meshes) / hemisphere; MeshPhysicalMaterial fields (clearcoat, transmission, thickness, ior, sheen…), toon, flatShading, side; flags pick: 'through', origin, anim: '<preset>' (through animationPreview.applyPreset), particles: '<preset>'; a --def <file.json> loader flag.
  • P1 — custom sky (bafc419): env: {preset:'custom', background: '#hex' | {top, bottom}, fog, ground, sun: {dir}, hemi, exposure}, committed through the environment module's own custom path (applyCustomPreset), so it saves and replicates as the ordinary environment singleton. environment.js gains two additive customPreset fields: a gradient background texture and an env-ground disc that takes the shadows. Stock presets and older saves are unchanged.
  • P2 — cards that look like the game (c87fbb4): the thumbnail renders with the scene's own background, fog, environment rig, authored lights and shadows. The tone curve is the post stack's, else none (what a composed desktop frame shows). The camera is thumb.camera, else view, else a projected 3/4 fit of the content. The authoring browser now uses the real GPU: --use-angle=gl had been falling back to SwiftShader.
  • P3 — the def schema (713aaba): every field, one line each, at the top of the script.

Suites

suite base now
author-kit (new) 58 checks, 0 FAIL
templates-modal ALL PASS (47 PASS lines) ALL PASS (47), 0 FAIL
template-modules ALL PASS (29) ALL PASS (29), 0 FAIL

svelte-check 336 errors / 47 warnings, list identical to base · vitest 196/196 · build green.
Counterfactuals (in each commit body): P0 → 2 FAIL, P1 → 4 FAIL (builder) and 3 FAIL (environment.js), P2 → 3 FAIL.
Byte-identity: level-blockout / towers / stars-room / untangle / waves authored before and after each phase. compare-authored.cjs finds their canonical session.json identical; only the card and inline-thumbnail sizes change, from the new renderer and the real GPU.

Deviation

The brief's "Waves card > 6 KB with centre luminance > 0.2" cannot be met honestly. Waves' live frames read 0.11–0.13 on the same metric, and the old grey-lit card read 0.198, so that check would pass the wrong card. The suite instead asserts:

  • the card uses the scene's own look (the Waves sky is its sunset background, not the old grey);
  • the card is larger than the old one (2110 B vs 1690);
  • a controlled sky def shows its gradient;
  • a lit studio def reads above 0.2.

The 0.2 bar should hold once 30-visuals-mod raises Waves' look.

For the integrator

  • environment.js changed (additive only; see above).
  • CHANGELOG line and CLAUDE.md notes (environment entry, author-templates entry, the SwiftShader gotcha), plus the schema table for modules AUTHORING.md: see the lane handover STATUS-30-author-kit.md, section 6.
  • Owed: the look of the new cards and custom skies on a real display, and a gradient sky with a ground in the Quest browser. Before/after cards are in lanes-30/after/30-author-kit/.

🤖 Generated with Claude Code

AlexZ005 and others added 4 commits September 23, 2026 00:35
…s, object flags

- build() gains capsule / plane / ring / icosahedron / dodecahedron (core three geometries,
  rebuilt from their parameters by ObjectLoader) and box `bevel` (+ bevelSegments): a port of
  three/examples RoundedBoxGeometry baked into a PLAIN BufferGeometry, because toJSON writes
  a subclass type ObjectLoader cannot rebuild (core Box params carry no bevel)
- light `kind`: spot (angle, penumbra, target) / directional (castShadow, shadowMapSize,
  frustum FITTED to the built meshes in the light's own frame; `fit: false` opts out) /
  hemisphere (groundColor); spot + directional follow createLight (cast by default, the V-1
  bias pair) and aim by ROTATION at `target` (24-E1). point (no kind) is untouched
- materials: `physical: true` or any physical-only field (clearcoat, clearcoatRoughness,
  transmission, thickness, ior, sheen, sheenColor, sheenRoughness, iridescence,
  specularIntensity) -> MeshPhysicalMaterial; `toon: true` -> MeshToonMaterial;
  `flatShading`, `side: 'double'|'back'`; emissiveIntensity as before
- flags: `pick: 'through'` -> userData.pick; `origin: [x,y,z]` -> userData.origin;
  `particles: '<preset>' | {preset, ...patch}` -> userData.particles from particlePresets;
  `anim: '<preset>' | [..]` -> animationPreview.applyPreset (by key or name), an ordinary
  authored clip (not playing — a Play Animation node runs it)
- loader: `--def <file.json[,..]>` adds defs from JSON (one or an array); a same-slug def
  REPLACES the DEFS entry. Unknown object types now throw instead of silently becoming cones
- suite author-kit (new): authors a def-under-test via --def/--only into a temp dir, loads it
  back through sessions.readSessionZip + applySession, one check per feature: 40 PASS
- byte-identity: level-blockout/towers/stars-room/untangle/waves authored before and after,
  scripts/compare-authored.cjs reports SAME for all five (thumbs identical in size)
- counterfactual: 'clearcoat' dropped from PHYSICAL_KEYS + the pick line removed -> exactly
  "physical: clearcoat 0.8 survives (0)" and "pick: 'through' lands on userData.pick" FAIL
- held: templates-modal 47 / template-modules 29 PASS lines at base (no src change in this
  commit); svelte-check 336/47 identical list; vitest 196; build green

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, sun, hemi

- a def `env` may be {preset:'custom' | <preset>, base?, exposure, background:'#hex' |
  {top, bottom}, fog:{color, near, far} | null, ground:{color, roughness?}, sun:{color,
  intensity, dir | position} | null, hemi:{sky, ground, intensity} | null}; colours may be
  numbers. It builds a payload from a base preset and commits it through the environment
  module's own custom path (applyCustomPreset), so the scene saves it as customPreset and a
  peer / late joiner gets it on the existing environment singleton. The payload's own
  exposure stays 1 and the def's exposure is the STATE multiplier (applyCustomPreset would
  otherwise square it). A plain preset env takes the old line verbatim
- environment.js (ADDITIVE, absent on every stock preset and every older save):
  `gradient: {top, bottom}` -> a cached 2x256 CanvasTexture background (`background` keeps
  the flat horizon colour for the backgroundColor store and older peers); `ground: {color,
  roughness?}` -> an `env-ground` disc in ENV_ROOT (scene root, never synced or saved as an
  object) that receives the sun's shadows, so the ShadowMaterial catcher stands down while
  it shows; hidden in wireframe and in passthrough (it would cover the real room).
  Read only through skyGradientOf / skyGroundOf (a malformed value reads as absent)
- the per-def reset uses environmentRestore(null) — setEnvironment('studio') kept a custom
  payload in the state, which environmentSnapshot would have saved into the NEXT def
- suite author-kit: + a sky section (state, texture background, fog, ground visible,
  catcher down, sun dir, hemi, exposure not squared) and a PIXEL check on the loaded scene:
  sky bands R 206 vs 81 (upper redder), B 206 vs 81 (lower bluer) — 53 PASS
- counterfactuals: the builder ignoring the gradient -> 4 FAIL (saved gradient, texture
  background, both pixel bands 34/34, 255/255); environment.js skyGradientOf -> null ->
  3 FAIL (texture background + both pixel bands)
- byte-identity: level-blockout/towers/stars-room/untangle/waves SAME vs the pre-lane build
- held: templates-modal 47/0, template-modules 29/0 (= base); svelte-check 336/47 with an
  identical list; vitest 196; build green on this environment.js

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n the real GPU

- the card renders with the SCENE's look: the live background (flat or the p1 gradient
  texture), its fog, the environment rig cloned from the scene root (hemi + sun + catcher /
  ground + extra env lights, at the intensities the viewport uses) and the authored lights
  (spot/directional targets seated on their -Z forward, the lightHelpers rule); shadows on
  (PCF). The private hemi + directional pair is the fallback ONLY for a scene with no light
- tone mapping = the post stack's Tone mapping curve when it has one, else NONE — what a
  composed desktop frame shows (the default Shaded+AO view keeps the composer running, and
  the renderer's own ACES never reaches a composed frame — the documented gotcha). MEASURED:
  ACES darkened the Waves card to 0.040 centre luminance against the live frame's 0.11-0.13;
  none reads 0.086. `thumb.toneMapping: 'agx'|'aces'|'neutral'|'reinhard'|'cineon'|'linear'|
  'none'` overrides per def
- camera: `thumb.camera`, else the def's `view` (NEW — the view the file opens on), else a
  3/4 PROJECTED fit of the content box (camera markers and floor-like slabs excluded — a thin
  mesh covering over a quarter of the footprint), so a 30x40 m ground no longer shrinks every
  game piece to a speck. Camera markers are hidden in every card now (chrome, not scenery)
- the authoring browser uses the per-platform ANGLE backend (vulkan on Linux, the helpers.cjs
  GPU_ARGS): `--use-angle=gl` fell back to SwiftShader, so every card was a software render.
  The run now prints its GPU line and WARNs on SwiftShader
- suite author-kit: + card checks — the sky def's card shows the authored gradient (top R 242
  / bottom B 242), the studio kit card reads (0.416 > 0.2), and the Waves def from the sibling
  modules checkout shows its OWN sunset sky (51,32,48 vs the scene's 51,32,47) and grew past
  the old card (2110 B vs 1690). 58 PASS
- DEVIATION (QUESTIONS-30-author-kit fork 1, recommendation taken): the brief's "Waves card
  > 6 KB with centre luminance > 0.2" is not reachable truthfully — the Waves scene is dark
  (its live frames read 0.11-0.13 on the same metric) and the OLD grey-lit card read 0.198, so
  a > 0.2 check would pass the wrong card. The 0.2 bar is asserted on a lit controlled scene
- counterfactual: HEAD's old thumbnail block restored (private lights, grey, whole-bounds) ->
  3 FAIL: the gradient card (top R 80 / bottom B 80), the Waves size (1696 B) and the Waves
  sky (34,42,51 = the private grey)
- scene content: level-blockout/towers/stars-room/untangle/waves canonical session.json SAME
  as the pre-lane build (only the card and the inline thumbnail sizes differ — new renderer,
  and the inline one now comes from a real GPU)
- no src change in this commit: svelte-check 336/47 and build as at p1; held suites as at p1

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- a "THE DEF SCHEMA" block at the top of scripts/author-templates.cjs: def-level fields (kind,
  identity, modules/installModules, generate/layout, objects, env, gravity/physics, post,
  graphs/hud/shaders/animations, music/sounds, view, thumb {camera, sceneGroups, toneMapping},
  contest), every object type with its params and defaults, the material fields (standard,
  physical, toon), the object flags (physics, shadow, pick, origin, anim, particles), the custom
  sky, the loader flags (--out, --only, --def, APP_URL, MODULES_REPO) and the card rules
- comment-only: node --check clean; the modules repo AUTHORING.md table is handed to the
  integrator (this lane may not edit the modules repo)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant