Skip to content

feat(shell): shared cluster-wide "scene plinth" hosting the SceneRack #259

Description

@bradleypmartin

Surfaced from #225 PR1 (#250 / #254) headset smoke (Brad, 2026-05-22).

"might even need ANOTHER plinth aside from the one we've made and the #226 plan: the scene selector is a little janky-looking now just floating up in the air. THIS theoretical 'scene plinth' should probably be shared among all the exhibits in a common world location." — Brad

The SceneRack (src/shell/SceneRack.ts) is shell-owned cluster navigation — one row of SceneTab bubbles at the same world position across every cluster member. After PR1 (#250) it tracks the control-plinth z (SCENE_RACK_Z = 0.05) so the bubbles aren't stranded over the cutout, but they still float in mid-air with no surface to anchor against.

A third plinth, not the existing two

The cluster is heading toward a trio of plinth types:

Plinth Scope Source
Control plinth per-exhibit knobs/dials/readouts #225 (delivered v0 in #250)
Info plinth per-exhibit in-world instructional reader #226
Scene plinth (this issue) cluster-wide navigation surface — one shared world location this issue

The defining feature versus #225 / #226 is shell-owned, single instance, shared across every cluster scene — never re-allocated, never per-exhibit. That ownership shape is the same as SceneRack itself today; the visual upgrade is adding the surface beneath it.

Direction (open)

  • Footprint and silhouette — probably distinct from the drafting-table-console silhouette of the control plinth, since the role is different (navigation between scenes vs. operating one scene's controls). Could read more as a museum kiosk / lectern / vitrine.
  • Worldspace placement — needs to compose with the cluster's existing staging (floor, railing, contrast pit) without competing for the user's attention against the math object. The current SceneRack anchor at (-0.44, 1.73, 0.05) is the starting point; the plinth lifts the bulbs off of "floating in air" toward "this is the scene-selector station."
  • Ownership — shell-owned, allocated once at boot in shell.ts alongside the SceneRack itself, never per-exhibit. Lifetime is the shell lifetime, not the exhibit lifetime. This is the cleanest break from feat(staging): control plinth hosting interactive UI (sub-epic) #225 (exhibit-owned, allocated in mount()).
  • Composition with the cluster's other staging — the scene plinth is the FIRST shell-owned worldspace plinth, so it sets the precedent for the v1.0.md §4 "persistent worldspace plinths default to shell-owned" rule that the control plinth (feat(staging): control plinth hosting interactive UI (sub-epic) #225) deliberately broke. Worth a callout in v1.0.md when this lands.

Open questions for plan-doc / roundtable

Code anchors

  • SceneRack today: src/shell/SceneRack.ts — anchor constants at file top, currently SCENE_RACK_Y = 1.73, SCENE_RACK_CENTER_X = -0.44, SCENE_RACK_Z = 0.05.
  • Allocation site: src/shell/shell.ts step 5 (#150) — const rack = new SceneRack({...}); scene.add(rack.group);. The "scene plinth" would slot in alongside it.
  • Cluster context: src/shell/clusters.ts (cluster identity), src/shell/Exhibit.ts (cluster-membership filter).

Refs

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions