Commit Graph
10 Commits
Author SHA1 Message Date
adminandClaude Opus 5.5 24d360aeec Add zoom steps and a larger start caption to the game link (#266)
game-maker / gate (push) Successful in 4m5s
game-maker / suite (push) Failing after 12m45s
The released game only ever zoomed in whole steps up to 400%, so a
small camera on a large screen stayed far smaller than it could be.
The "Click to play" caption was drawn in the 11 px panel title size
and was easy to miss.

- GAME_SCALE_STEPS gains 300%, 500% and 600%. The game tab picker,
  Auto in the editor and the game link all read the same list.
- The start caption takes its size from the new Theme.captionSize
  (16) instead of a constant in GameScreen.
- The player page keeps the default arrow cursor at all times. It no
  longer switches to the hand over the caption.

Tests:
- view.test: Auto for 320x180 in 2000x2000 is now 6, with cases
  for 3 and 5. play-settings.test takes 2.5 and 8 as invalid steps.
- e2e 60 checks the caption against the panel title size and the
  arrow cursor before and after the start. Module 03 follows the new
  step list.
- ./check.sh 2808 tests, CHECK EXIT 0 (before the last Theme tweak,
  which changes no test). Full e2e run ALL PASSED, 1574 checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 14:14:54 +02:00
adminandClaude Opus 5.5 30de4d35a8 Give the scene tab a header with Fit and the eye (#245)
game-maker / gate (push) Successful in 3m21s
game-maker / suite (push) Failing after 9m15s
The scene view had no header bar of its own, and its eye sat in the
top bar. Switching between Scene and Game also showed two different
pictures, since nothing tied the free view to the camera.

- Theme.headerPadding (4) replaces Theme.padding in the top bar and
  in TabHeader, for the padding and for minHeight. Both bars shrink
  from 40 to 32 px. Nothing else uses the new value.
- The new ScenePane wraps the scene view in a header bar with Fit
  and the visibility eye. The eye is gone from the top bar, which
  keeps the menu, undo and redo.
- Fit with an active camera shows the world exactly as the Game tab
  does at its chosen step: the same zoom, and the camera centre on
  the same screen pixel. The rule is the pure freeViewOfCamera in
  viewport/view.ts, which also mirrors the letterbox snapping.
- Fit without a camera frames all content on a whole step, as
  before.
- New hook __gm.sceneHeaderAt(name). e2e 46g opens the eye there.
- The doc comment above Theme.treeIndent went away in the working
  tree along with this. It is committed as found.

Not checked: the two views only match while they have the same size.
With the tilemap panel open the scene view is narrower, and Auto may
pick a smaller step there.

Tests:
- ./check.sh: 178 files, 2575 tests, CHECK EXIT 0
- 2 new unit tests in view.test.ts: three cameras times four steps
  land on the same screen point as in the Game tab, Auto stays whole
- e2e 3h (2 checks): a real click on Fit at Auto and at Fit, crate,
  camera frame and view box match in both tabs
- GM_STEPS=1-3,46: ALL PASSED, 94 checks
- Counter-probes: without the centre offset the unit test fails,
  with Fit ignoring the camera both 3h checks fail

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 12:57:49 +02:00
adminandClaude Opus 5.5 98b9b300d9 Zoom the scene view further in, up to 64 device pixels
The scene view stopped at 24 device pixels per world pixel, which is
too little to work on single texels of small pixel art.

- FREE_ZOOM_STEPS gains the steps 32, 48 and 64. All of them are whole
  numbers, so every texel keeps the same width on screen.
- The tile editor takes the same steps, so its fit can now land above
  24 on a small board.
- The unit test and the step list in e2e 39 follow the new top step.

Tests:
- ./check.sh: 178 files, 2573 tests, CHECK EXIT 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 12:12:01 +02:00
adminandClaude Opus 5.5 021a6dcb56 Zoom the tile tab in the same steps as the scene view
game-maker / gate (push) Successful in 2m58s
game-maker / suite (push) Failing after 8m34s
The tile tab zoomed freely, so the pixels of a tile could end up
unevenly wide at odd factors. Scene view, container tab and animation
preview already snap to FREE_ZOOM_STEPS. The tile tab now does the
same, so every pixel editor zooms alike.

- The wheel steps through FREE_ZOOM_STEPS, counted in device pixels.
  The board position is rounded to whole device pixels.
- New wheelSteps() in src/viewport/view.ts turns wheel events into
  steps: one notch is one step, a trackpad gathers 50 px per step.
  FreeViewport uses it too, so the rule exists only once.
- Fit takes the largest step at which the whole board fits. Refitting
  on a new tab or board size stays as before.
- panAndZoom takes an optional zoom rule instead of limits. Graph and
  node board keep zooming freely.
- A saved view from before the steps snaps to the nearest step.
- The cap parameter of frameBoxes from 4027afc has no user anymore.
  It is removed together with its unit test.

Fit rounds down, and below 100 percent the steps are far apart. In the
small e2e window the 48 px board lands at 25 instead of 41 percent,
the 16 px board at 100 instead of 124 percent.

Tests:
- check.sh: 161 files, 2370 tests, exit 0 (-1 cap test,
  +1 wheelSteps test)
- e2e 1-5 and 39: all passed, 169 checks. Three checks in 39 now
  expect steps: Fit on a step with the next one too large, one notch
  goes 0.25 to 0.5, 16 px tiles refit to at least 100 percent.
- Counter check: a free Fit factor fails exactly those three checks
  (zoom 0.413 and 1.2396).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 10:30:41 +02:00
adminandClaude Opus 5.5 5399ef17e5 Snap the scene view zoom to pixel exact steps
The wheel zoomed smoothly and fit computed any factor, so the scene
view almost never showed pixel art with even texels. Under Windows
scaling even zoom 1 was off. The zoom now only takes steps that give
every texel the same number of screen pixels.

- The zoom counts device pixels per world pixel. freeView divides by
  the renderer resolution, so zoom 1 is one screen pixel per texel.
- FREE_ZOOM_STEPS: 1/8, 1/4, 1/2, then 1 to 6, 8, 12, 16 and 24.
- The wheel moves one step per notch. A trackpad collects its travel
  and steps every 50 px.
- Fit rounds down to the next step. A saved zoom from before snaps to
  the nearest step on a log scale.
- Pan, drag, grid and resize use CSS pixels per world unit, so they
  still follow the pointer under Windows scaling.
- Always on, no toggle, as decided in the session.

Tests:
- 4 unit tests: zoom 1 at 125%, whole steps, wheel steps and ends, fit
  rounding and snapping of a saved zoom.
- Counter-check: without the ratio in freeView the 125% test fails.
- check.sh: 156 files, 2320 tests, CHECK EXIT 0.
- e2e 1-17,28,30,38-40: 726 checks passed on the steps before the
  final values (up to 8). Not rerun on the final steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 10:40:54 +02:00
adminandClaude Opus 5.5 22a89ed0f0 Keep game view steps pixel exact under Windows display scaling
At 125% Windows scaling the game view drew 100% as 1.25 screen pixels
per camera pixel, so pixel art showed texels of uneven width even at
the round steps. The steps now count device pixels instead of CSS
pixels.

- gameScaleFactor, cameraFactor and cameraView take the device pixel
  ratio. 100% is one screen pixel per camera pixel, 200% two.
- Auto picks the largest step that fits in device pixels. Fit reports
  its factor in device pixels too, e.g. 156% at 125% scaling.
- Fixed steps start the frame on a whole device pixel.
- The game view reads the ratio from the renderer resolution.

Limits: main.ts caps the resolution at 2, so scaling above 200% is
stretched by the browser again. A changed ratio at runtime only counts
after a reload, as before.

Tests:
- 2 unit tests at 125%: 100% is one device pixel on a whole pixel,
  auto and fit count device pixels.
- Counter-check: without the conversion the 100% test fails.
- check.sh: 156 files, CHECK EXIT 0 on the combined working tree.
- No e2e: the harness runs at devicePixelRatio 1, same math as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 10:40:43 +02:00
adminandClaude Opus 5.5 9ef360ba1b Let the game view show the picture at a chosen scale (#225)
game-maker / gate (push) Successful in 2m57s
game-maker / suite (push) Failing after 9m28s
The game view always stretched the camera picture to fit the pane.
Pixel art came out blurred at odd factors, and there was no way to
see the game at its real size. The view now has a header with a
scale drop-down, and 100 % is the default.

- The header of the new GamePane offers Auto, Fit, 25 %, 50 %,
  100 %, 200 % and 400 %. Auto and Fit show the factor they land
  on, e.g. "Auto · 100%", and follow the pane when it resizes.
- 100 % means one screen pixel per pixel of the camera resolution
  (width x height). The camera zoom scales the world on top of
  that, so a zoomed camera still fills the same frame.
- Auto takes the largest fixed step that fits the whole picture
  and falls back to 25 % when nothing fits. Fit keeps the old
  behaviour.
- A picture larger than the pane is cropped around the camera
  centre. Fixed steps start on a whole pixel so pixel art stays
  sharp at 100 %.
- The choice is kept in the browser like "Play starts". Nothing
  is written into the project.

Found on the way: the first draft applied the step to the world
instead of the camera resolution. The camera zoom then had no
effect at 100 %, which the existing check 12c caught (zoom 1.37
measured as scale 1).

The CI smokes were not run locally, because that would reseed
projects the user works in. All three smoke cameras are 640x360
and fit the 670x383 harness view at 100 %.

Tests:
- ./check.sh: 156 files, 2298 tests, CHECK EXIT 0 (before 2290).
- 8 unit tests in tests/viewport/view.test.ts for whole-pixel
  steps, cropping, Auto and Fit with fallback, and zoomed cameras.
- 7 e2e checks in 03g. e2e 1-17,28,30,38-40: ALL PASSED, 727
  checks.
- Counter-checks: no cropping, no rounding, no factor reported to
  the header, and no zoom share each fail their own tests.
- Check total: 1367 (CI at c1a702b) + 7 = 1374, computed only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 07:02:48 +02:00
rootandClaude Opus 5 4d84231b9f Trim needless comments and fix the picker width
Remove comments that only restate the code, keeping the section banners
and the notes that carry a reason, a measured fact or an external
contract.

ButtonOptions.width claimed to be a fixed width but only set minWidth,
so the Graph and Texture pickers grew with the name they showed. It is
now what it promises, with a separate minWidth for the buttons that have
two forms. Narrow buttons shrink their padding, otherwise a 24px icon
button had 8px left for its glyph and truncate dropped it entirely.

__gm.labelsDropped() guards that class: the overflow guard only saw text
that was too wide, never a label truncated to nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 15:52:05 +02:00
rootandClaude Opus 5 d54a620ebd Add ESLint and Prettier, and close the node test gaps
Tooling:
- Prettier as the single formatting authority (110 columns, single quotes,
  measured against the existing style); Markdown excluded because table-cell
  padding turns the README glossary into 1000-character lines.
- Type-aware ESLint ending in eslint-config-prettier, so a rule always means
  "this is a bug", never "this looks different".
- .editorconfig and an `npm run check` that runs typecheck, lint, format and
  tests in one go.

Findings fixed on the first run: three more duplicate imports, four
String(unknown) calls (parameter types narrowed instead of casts), two dead
initialisers, two redundant casts, a console.log for a real error. Two
warnings were false here and are disabled with a reason in place.

Tests 132 -> 269:
- node-catalog.test.ts covers every node with a run(), with a guard that fails
  when a new node has no row.
- behavior-events.test.ts covers the ten event nodes through a running World,
  checking timing rather than existence.
- Input's state machine (press/release/releaseAll) is reachable without DOM
  events now; the DOM handlers are thin adapters.

Compare fell back to == without a configured operator although the schema
default is <; aligned.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 10:02:22 +02:00
rootandClaude Opus 5 f140c2fd77 Fix findUsages/undo/node-lookup bugs, split Viewport and Editor, share command and inspector helpers
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 09:22:49 +02:00