tower / commit
feat(exterior): open on the true hull, and remember the choice
README.md | 3 ++- decisions.md | 15 +++++++++++++++ design.md | 3 ++- index.html | 4 ++-- src/ui/app.ts | 11 +++++++++++ src/views/exterior.ts | 3 ++- 6 files changed, 34 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 93f1f16..f1bf538 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,8 @@ Any selection updates the URL, so a link is always shareable: kilometre of hull, a window at each cap, the interior's own star field, the 244 km collector flying ahead and the beam converging into the sun cap. Each piece is captioned. -The hull reads two ways and the **Hull** switch picks one. **True** is the outer +The hull reads two ways and the **Hull** switch picks one; it opens on True and +remembers whichever you last chose. **True** is the outer skin: bare structure, and both caps real windows — look in through either and the land is actually there, hazed exactly as the interior view hazes it and receding 540 km down the tube. It is the only line diff --git a/decisions.md b/decisions.md index 33f85c7..eaa1c4b 100644 --- a/decisions.md +++ b/decisions.md @@ -1936,3 +1936,18 @@ rolls a star, and only stars inside a one-cell shell around the eye count, which holds the same number of cells per steradian in every direction. The pinwheel is kept by turning the direction about z before the lookup, and the density matches what the old field had at its pole, so the far cap window looks as it did. + +## D-061 — The exterior opens on the true hull, and remembers the choice + +**Implemented at the author's request.** X-ray was the default because, before D-060, +the true hull showed little: a bare cylinder, a checkered cap, and land only through +the far window. Now both caps are windows onto the hazed interior, so the true hull is +the better first look, and it is what Tower actually looks like. + +**The choice is remembered** in localStorage under `tower.exteriorHull`, alongside the +active view (D-025) and the camera. It is restored into the Hull control at startup, +before the exterior is built, because the exterior reads its reading from that control +when it is first constructed. Switching to another view and back never rebuilds the +exterior, so the reading survives that as well. An unreadable or unknown stored value +falls back to true. The screenshot script selects a reading explicitly for each shot, +in a fresh browser context, so it is unaffected. diff --git a/design.md b/design.md index e328e57..d4f6258 100644 --- a/design.md +++ b/design.md @@ -736,7 +736,8 @@ is the outer skin: bare structure, with a window at each cap. **X-ray** wraps the terrain raster onto the outside instead — from outside Tower is structure, so what that texture shows is what is *inside*, which makes it a diagram and not a view. Both are worth having and they are not the same claim, so the -control is a two-way switch rather than a checkbox. +control is a two-way switch rather than a checkbox. **True is the default**, and the +last reading chosen is remembered across reloads and view switches (D-061). **The inside of Tower is the interior view's own model** (D-060), not a lookalike. The displaced ground, both glazed caps, the far cap's bore and the beam are built diff --git a/index.html b/index.html index f1367c4..023f758 100644 --- a/index.html +++ b/index.html @@ -45,8 +45,8 @@ <div id="exterior-options" class="hidden"> <label>Hull <select id="f-ext-view"> - <option value="true">True — what Tower looks like</option> - <option value="xray" selected>X-ray — the inner surface projected out</option> + <option value="true" selected>True — what Tower looks like</option> + <option value="xray">X-ray — the inner surface projected out</option> </select></label> <p class="hint">True shows the outer skin: bare hull, and a window at each cap — look in through either and the land is really there, hazed as it is diff --git a/src/ui/app.ts b/src/ui/app.ts index cc33396..86f0a5a 100644 --- a/src/ui/app.ts +++ b/src/ui/app.ts @@ -22,6 +22,8 @@ import { eyeHeightFromSlider, sliderFromEyeHeight } from './scales.js' type Tool = 'select' | PlaceKind type ViewName = 'map' | 'exterior' | 'interior' const VIEW_KEY = 'tower.view' +/** The exterior's hull reading, remembered across reloads like the view itself (D-061). */ +const HULL_KEY = 'tower.exteriorHull' const isView = (v: string | null): v is ViewName => v === 'map' || v === 'exterior' || v === 'interior' @@ -565,8 +567,17 @@ export class App { this.map.draw() } const ext = $<HTMLSelectElement>('f-ext-view') + // Restored into the control itself, which is what the exterior reads when it is + // first built — so a view opened on load starts in the remembered reading. + try { + const stored = localStorage.getItem(HULL_KEY) + if (stored === 'true' || stored === 'xray') ext.value = stored + } catch { /* unreadable storage just means the default, true */ } ext.onchange = () => { if (this.exterior) this.exterior.showTerrain = ext.value === 'xray' + try { + localStorage.setItem(HULL_KEY, ext.value) + } catch { /* not remembering the hull is survivable */ } } } diff --git a/src/views/exterior.ts b/src/views/exterior.ts index f63568f..2c0d288 100644 --- a/src/views/exterior.ts +++ b/src/views/exterior.ts @@ -119,7 +119,8 @@ export class ExteriorView { private worldToTower = new Matrix4() private eyeInTower = new Vector3() private terrainMap: Texture | null = null - private _showTerrain = true + /** True mode by default (D-061); the app sets the remembered reading on construction. */ + private _showTerrain = false private raycaster = new Raycaster() private running = false private lastFrame = 0