diff --git a/README.md b/README.md index 9acf43ca..07b8ecd3 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ A browser-based tool "one step before a game engine": create **assets** (scenes, sprites), place them into scenes, tweak their properties in an inspector and press **Play** โ€“ all in one program, all drawn inside a single WebGL canvas. +![](screenshot.png) + Live: ยท Widget playground: **The documentation is the wiki:** โ€“ every concept, @@ -40,7 +42,7 @@ npm run build # writes dist/ and regenerates index.html; the folder is wh The browser suite and the three example games need a machine with a GPU: ```bash -node tools/seed-e2e.mjs && node tools/e2e.mjs # the editor, 1147 checks (GM_STEPS=20 for one step) +node tools/seed-e2e.mjs && node tools/e2e.mjs # the editor, 1148 checks (GM_STEPS=20 for one step) # every tool signs in first โ€“ see the Accounts page node tools/seed-jumprun.mjs && node tools/smoke-jumprun.mjs node tools/seed-tetris.mjs && node tools/smoke-tetris.mjs diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 00000000..f3191383 Binary files /dev/null and b/screenshot.png differ diff --git a/src/editor/panels/Toolbar.ts b/src/editor/panels/Toolbar.ts index 30015827..01a65732 100644 --- a/src/editor/panels/Toolbar.ts +++ b/src/editor/panels/Toolbar.ts @@ -148,6 +148,24 @@ export class Toolbar extends HStack { this.status.setStyle(state.saveStatus === 'error' || state.saveStatus === 'conflict' ? 'body' : 'small'); } + /** + * The row lays itself out first, then the two run buttons are moved onto the middle of the bar. + * The row alone cannot put them there: the two spacers around them share the free space with the + * flexible notice, so each gets a third of it and the pair ends up left of centre. Middle means + * the middle of the bar here, not the middle of what the row had left over. It never travels + * past the notice, so a narrow window pushes the pair back rather than one label over another. + */ + override layout(): void { + super.layout(); + const width = this.pauseButton.x + this.pauseButton.w - this.playButton.x; + const leftMost = this.redoButton.x + this.redoButton.w + this.gap; + const rightMost = this.notice.x - this.gap - width; + const x = Math.round(Math.max(leftMost, Math.min((this.w - width) / 2, rightMost))); + const shift = x - this.playButton.x; + this.playButton.position.set(this.playButton.x + shift, this.playButton.y); + this.pauseButton.position.set(this.pauseButton.x + shift, this.pauseButton.y); + } + override redraw(): void { this.bg.clear(); this.bg.rect(0, 0, this.w, this.h).fill(Theme.colors.panelHeader); diff --git a/src/editor/panels/icons/redo.svg b/src/editor/panels/icons/redo.svg index 9d9d33fb..56b4ccb4 100644 --- a/src/editor/panels/icons/redo.svg +++ b/src/editor/panels/icons/redo.svg @@ -1,5 +1,5 @@ - - + + diff --git a/src/editor/panels/icons/undo.svg b/src/editor/panels/icons/undo.svg index 045e92c2..99d3d6d1 100644 --- a/src/editor/panels/icons/undo.svg +++ b/src/editor/panels/icons/undo.svg @@ -1,6 +1,8 @@ - - - + + + diff --git a/tools/e2e/46-topbar.mjs b/tools/e2e/46-topbar.mjs index fc683e4a..f22e50fa 100644 --- a/tools/e2e/46-topbar.mjs +++ b/tools/e2e/46-topbar.mjs @@ -34,6 +34,17 @@ export async function topbar(t) { buttons.pauseEnabled === false, JSON.stringify(buttons), ); + // The pair is centred on the bar itself. The row cannot do that on its own: the spacers around + // the two buttons share the free space with the flexible notice and so get a third of it each, + // which used to leave the pair well left of the middle. + const play = await json('__gm.toolbarAt("play")'); + const pause = await json('__gm.toolbarAt("pause")'); + const barCentre = await json('window.innerWidth / 2'); + check( + 'play and pause sit on the middle of the bar, not on the middle of what is left over', + Math.abs((play.x + pause.x) / 2 - barCentre) <= 2, + JSON.stringify({ middle: (play.x + pause.x) / 2, barCentre }), + ); await shot('46-topbar'); // 46b. The one menu. Four entries, and the separator between what opens a project and what