diff --git a/docs/DESIGN.md b/docs/DESIGN.md index f33626a..1f7bdbc 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -147,8 +147,9 @@ above, including: wall material and filter settings. G no longer picks, as the owner requested (it is now Replace). - **The build menu** is a bar of tabs and icon tiles along the bottom: Structure, Moving, Liquids, Machines, Molds. Hover a tile for its full description, cost and placement help; - gamepad players see the selected tile’s popup. The top-left card is hidden while building, - with variants, ghosts and status kept in the bar so the world stays clear. + gamepad players see the selected tile’s popup. While building, the top-left card shows a + compact summary (name, cost, variant chips, Replace, ghosts, how to place, status); the full + description is in the hover popup. - **No length limit when dragging.** Blocks out of the bot's reach become ghosts that it builds when it gets there. - **Pipes are thin:** sand, water and anything else loose passes them. Pumps and outlets are @@ -168,6 +169,9 @@ above, including: - **Replace is held G, not Ctrl.** The owner hit the browser's Ctrl+W (close tab) and Ctrl+D (bookmark) while replacing and flying with WASD, and the game ignored WASD while Ctrl was held. +- **The build tool has a compact top-left card** like the other tools. The owner asked for it + back after it was hidden; the long description stays in the hover popup. + ## Ideas not built yet - **Concrete**, as a stronger wall material from rubble. diff --git a/docs/PROJECT_MAP.md b/docs/PROJECT_MAP.md index 9eeae9e..5316df8 100644 --- a/docs/PROJECT_MAP.md +++ b/docs/PROJECT_MAP.md @@ -392,12 +392,12 @@ The notebook (N): milestones, market, wallet, blueprints, controls. The tool hotbar and what is selected. - functions: renderHotbar, toolId, steering, modShift, grainAt, selectTool, bagMaterials, mixList, ensureDropMat, piece -### src/ui/build-menu.js (104 lines) +### src/ui/build-menu.js (101 lines) The build menu along the bottom: categories, piece tiles and their icons. -- functions: pieceIcon, catOf, selectBuildCat, cycleBuildCat, renderBuildBar, setupBuildBar +- functions: pieceIcon, catOf, selectBuildCat, cycleBuildCat, buildVariantChips, renderBuildBar, setupBuildBar - variables: BUILD_CATS, BUILD_ORDER, PIECE_ICONS, lastBuildKey, lastBuildMenu -### src/ui/selection.js (228 lines) +### src/ui/selection.js (234 lines) The selected tool and piece: R / Q / E, drill width, filter picker, the selection card, the bag panel. - functions: pieceUsesWall, setDrillWidth, tuneUnderCursor, cycleItem, cycleWall, rotate, toggleCollect, pickFilterUnderCursor, toggleFilterMat, toggleCollectUnderCursor, setBrush, pieceV, pieceExtra, filterChoices, matList, filterParts, filterSentence, applyFilterRun, openFilterPicker, filterBlockAt, chipCost, pieceCostNow, renderSelCard, renderBag - variables: lastBagKey diff --git a/docs/agent-log.md b/docs/agent-log.md index 7611835..816645f 100644 --- a/docs/agent-log.md +++ b/docs/agent-log.md @@ -4,6 +4,22 @@ What agents have done, newest first. Add an entry for every piece of work: the d note or request it was for, what changed, the files touched, the tests run, and anything left open or not verified. Keep each entry short; the git history has the details. +## 2026-10-23: compact build card top-left (Claude Code, with Codex) + +Note: "build tool has no info box like the other tools." The owner chose a compact card. + +- `src/ui/selection.js`: the build tool has a card again: Q, piece name, cost (red if short), E; + variant chips, Replace · G and ghosts waiting; one how-to line; the status line. No long + description; that stays in the hover popup. +- `src/ui/build-menu.js`: the `.bb-status` row is gone (its contents are on the card); the + variant chips are shared through `buildVariantChips(P)`. `src/styles/style.css`, + `docs/DESIGN.md`, `docs/PROJECT_MAP.md`. +- `test/play.py`: the card is visible while building with name and cost and without the + description; status and Replace · G are read from the card; no `.bb-status` (122 checks pass). + All 11 headless suites pass; `t_smooth.py`'s half-resolution check is still flaky under load. +- Shots: `shots/build-card-*` (belt and wall, both looks, 1280×800 and 900×700) look right. +- Open: at 900px wide the bottom-left hover panel still sits partly under the build bar. + ## 2026-10-23: Replace is held G, not Ctrl (Claude Code, with Codex) Note: "i see the issue was ctrl+w closing the tab… it happens for the bookmark hotkey too. maybe diff --git a/src/styles/style.css b/src/styles/style.css index c6000a3..84902ab 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -63,8 +63,6 @@ canvas#game.nocursor { cursor: none; } .bb-tile.on svg { color: var(--melt-hot); } #buildbar { position: relative; } .bb-menu { display: flex; flex-direction: column; gap: 6px; } -.bb-status { display: flex; align-items: center; gap: 4px; min-height: 1.4em; overflow-x: auto; } -.bb-status .sw { flex-shrink: 0; } #bb-pop { position: absolute; bottom: calc(100% + 8px); width: min(calc(300px * var(--ui)), calc(100vw - 32px)); box-sizing: border-box; padding: calc(10px * var(--ui)); display: flex; flex-direction: column; gap: 8px; background: var(--plate); border: 1px solid var(--soot-3); border-radius: 5px; box-shadow: 0 4px 18px #0008; color: var(--bone); pointer-events: none; } .bb-title { display: flex; align-items: center; gap: 8px; } .bb-title svg { width: calc(26px * var(--ui)); height: calc(26px * var(--ui)); color: var(--melt-hot); flex-shrink: 0; } diff --git a/src/ui/build-menu.js b/src/ui/build-menu.js index 1dec89c..4551ac7 100644 --- a/src/ui/build-menu.js +++ b/src/ui/build-menu.js @@ -40,6 +40,18 @@ function cycleBuildCat(d) { const c = GAME.buildCat != null ? GAME.buildCat : catOf(piece().id); selectBuildCat((c + d + BUILD_CATS.length) % BUILD_CATS.length); } +function buildVariantChips(P) { + const dir = P.dirs ? P.dirs[GAME.pieceDir[P.id] || 0] : null; + // while dragging a line of belts, filters or tubes, the direction is the drag's + const dragging = GAME.drag && GAME.dragDir >= 0 && P.dirs; + const glyph = d => ({ left: '←', right: '→', up: '↑', down: '↓' })[d] || ''; + const dirChip = !P.dirs ? '' : dragging ? `${glyph(P.dirs[GAME.dragDir])} ${esc(P.dirs[GAME.dragDir])} · from your drag` : `${glyph(dir)} ${esc(dir)} · R`; + const fc = GAME.filterCfg; + const sws = ms => ms.slice(0, 6).map(m => ``).join('') + (ms.length > 6 ? `+${ms.length - 6}` : ''); + return pieceUsesWall(P) ? `${esc(MD[WALL_OF[GAME.wallMat]].name.toLowerCase())} · R` + : P.filter ? `${fc.inv ? 'carries' : 'drops'} ${fc.m.length ? sws(fc.m) : 'nothing'} · F${dirChip}` + : dir ? dirChip : ''; +} function renderBuildBar() { const bar = $('buildbar'); if (!bar) return; const show = GAME.running && toolId() === 'build' && !GAME.paste && !GAME.selDrag && !selModeHeld(); @@ -47,10 +59,8 @@ function renderBuildBar() { if (!show) { lastBuildKey = ''; return; } const P = piece(), cat = GAME.buildCat != null ? GAME.buildCat : catOf(P.id), hov = GAME.bbHover; const ids = BUILD_CATS[cat][1], tip = PIECE_BY_ID[GAME.usingPad ? P.id : hov && ids.includes(hov) ? hov : '']; - const status = performance.now() - GAME.statusT < 3200 ? GAME.status : ''; - const ng = ghostBlocks.size + ghostMachines.length + ghostMolds.length; const afford = ids.map(id => canAfford(pieceCostNow(PIECE_BY_ID[id]), 1) ? 1 : 0).join(''); - const key = [cat, P.id, tip && tip.id, afford, GAME.wallMat, Math.round(money), GAME.replace, GAME.pieceDir[P.id], !!GAME.drag, GAME.dragDir, GAME.filterCfg.inv, GAME.filterCfg.m.join('.'), ng, ghostMissing, status, GAME.statusKind, innerWidth, innerHeight, SET.uiScale].join('|'); + const key = [cat, P.id, tip && tip.id, afford, GAME.wallMat, Math.round(money), GAME.pieceDir[P.id], GAME.filterCfg.inv, GAME.filterCfg.m.join('.'), innerWidth, innerHeight, SET.uiScale].join('|'); if (key === lastBuildKey) return; lastBuildKey = key; let h = '