From 17f47f6956eeafccc54ca12eacd67b72c8296e45 Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Sat, 10 Oct 2026 13:29:28 +0200 Subject: [PATCH] Drop the Gain's engraved name and centre its knob (#384) The plate was taller than its one knob needs, and the engraved "GAIN" only repeated the node's title. Without it the plate is square, and the knob sits in its middle. - The plate is 160x160 instead of 160x220, without the "GAIN" engraving. - The knob is centred on what it shows: the "DB" caption and the dial. Since #382 its number hangs inside the dial's open bottom, so it adds no height. - CAPTION_AIR (4) takes out the empty space above the caption's capitals. Without it the knob sat a little too low. Measured on a picture at zoom 0.8: 19 px of air above "DB" and 19 px below the number. The user's screenshot showed about 14 above and 35 below. Tests: - Unit hardware-view: 12 tests green. The layout test now asks for the same air above and below. - e2e 34 (melektaus-atx): ALL PASSED, 126 checks. - Gate (melektaus-atx): CHECK EXIT 0, 283 files, 4359 tests. Co-Authored-By: Claude Opus 5.5 --- src/editor/soundfx/GainPanel.ts | 6 +----- src/editor/soundfx/hardwareView.ts | 11 +++++++---- tests/editor/hardware-view.test.ts | 14 ++++++++++---- tools/e2e/34-sound.mjs | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/editor/soundfx/GainPanel.ts b/src/editor/soundfx/GainPanel.ts index c36e6423..7ab2ad6c 100644 --- a/src/editor/soundfx/GainPanel.ts +++ b/src/editor/soundfx/GainPanel.ts @@ -30,7 +30,6 @@ const DARK_ARC = 0x3b1a06; export class GainPanel extends Widget { private readonly plate = new Graphics(); readonly knob: Knob; - private readonly title: { ink: Text; edge: Text }; private readonly caption: { ink: Text; edge: Text }; constructor(host: GainHost) { @@ -38,7 +37,6 @@ export class GainPanel extends Widget { this.minWidth = GAIN_PANEL.w; this.minHeight = GAIN_PANEL.h; this.addChild(this.plate); - this.title = engrave(this, 'GAIN', 14); this.caption = engrave(this, 'DB', 11); const row = GAIN_ROW; this.knob = new Knob('', row.default, { @@ -70,13 +68,11 @@ export class GainPanel extends Widget { } override layout(): void { - const L = GAIN_LAYOUT; - const spot = L.knob; + const spot = GAIN_LAYOUT.knob; const size = this.knob.measure(); this.knob.position.set(Math.round(spot.x - size.w / 2), Math.round(spot.y - spot.size / 2)); this.knob.resize(size.w, size.h); placeEngraving(this.caption, spot.x, spot.y - spot.size / 2 - KNOB_CAPTION); - placeEngraving(this.title, L.title.x, L.title.y + 6); } override redraw(): void { diff --git a/src/editor/soundfx/hardwareView.ts b/src/editor/soundfx/hardwareView.ts index cc4fb448..1c4a3976 100644 --- a/src/editor/soundfx/hardwareView.ts +++ b/src/editor/soundfx/hardwareView.ts @@ -74,12 +74,15 @@ export const PANEL_LAYOUT: PanelLayout = { screws: screwsOf(PANEL), }; -/** The Gain as a device (#384): an orange plate with one big knob. */ -export const GAIN_PANEL = { w: 160, h: 220 }; +/** The Gain as a device (#384): an orange plate with one big knob and no name, as low as it allows. */ +export const GAIN_PANEL = { w: 160, h: 160 }; + +/** The air in a caption's line above its capitals, and the hair a tucked number hangs below the dial. */ +export const CAPTION_AIR = 4; export const GAIN_LAYOUT = { - title: { x: GAIN_PANEL.w / 2, y: 14 }, - knob: { x: GAIN_PANEL.w / 2, y: 120, size: BIG_DIAL }, + // Its number hangs in the dial's open bottom (#382), so the caption's ink and the dial are what to centre. + knob: { x: GAIN_PANEL.w / 2, y: (GAIN_PANEL.h + KNOB_CAPTION - CAPTION_AIR) / 2, size: BIG_DIAL }, screws: screwsOf(GAIN_PANEL), }; diff --git a/tests/editor/hardware-view.test.ts b/tests/editor/hardware-view.test.ts index 33a5c165..bc1f86ef 100644 --- a/tests/editor/hardware-view.test.ts +++ b/tests/editor/hardware-view.test.ts @@ -7,7 +7,9 @@ import { describe, expect, it } from 'vitest'; import { type Box, brushStrokes, + CAPTION_AIR, GAIN_LAYOUT, + KNOB_CAPTION, GAIN_PANEL, GAIN_TAPER, gainReduction, @@ -140,14 +142,18 @@ describe('the Gain (#384)', () => { const L = GAIN_LAYOUT; const knob = knobBox(L.knob); - it('holds its knob inside the plate, clear of the screws and below the title', () => { + it('holds its knob in the middle of the plate, clear of the screws', () => { expect(knob.x).toBeGreaterThanOrEqual(0); expect(knob.x + knob.w).toBeLessThanOrEqual(GAIN_PANEL.w); - expect(knob.y + knob.h).toBeLessThanOrEqual(GAIN_PANEL.h); - expect(knob.y).toBeGreaterThanOrEqual(L.title.y + 30); + // Its number hangs inside the dial (#382): from the caption down to the dial's edge is all it shows. + const top = L.knob.y - L.knob.size / 2 - KNOB_CAPTION; + const bottom = L.knob.y + L.knob.size / 2; + expect(top).toBeGreaterThan(0); + expect(top + CAPTION_AIR).toBe(GAIN_PANEL.h - bottom); expect(knob.x + knob.w / 2).toBe(GAIN_PANEL.w / 2); + const shown = { ...knob, y: top, h: bottom - top }; for (const screw of L.screws) - expect(overlap(knob, { x: screw.x - 7, y: screw.y - 7, w: 14, h: 14 })).toBe(false); + expect(overlap(shown, { x: screw.x - 7, y: screw.y - 7, w: 14, h: 14 })).toBe(false); }); it('turns 0 dB straight up and the quiet tail by in a fifth of the turn', () => { diff --git a/tools/e2e/34-sound.mjs b/tools/e2e/34-sound.mjs index 1d21b937..fc427de4 100644 --- a/tools/e2e/34-sound.mjs +++ b/tools/e2e/34-sound.mjs @@ -1059,7 +1059,7 @@ export async function sound(t) { 'a Gain node shows its panel with one knob between its ports; a drag turns it as one undo step, the wheel zooms the graph, a double-click resets it without a tab', gainShown.shown && gainShown.size.w === 160 && - gainShown.size.h === 220 && + gainShown.size.h === 160 && gainShown.knob.number === '-6' && gainShown.knob.enabled && Object.values(gainShown.inputs).length === 3 &&