2 Commits
Author SHA1 Message Date
adminandClaude Opus 5.5 4c7861b5b8 Keep the frame rate up while painting a big tilemap (#347)
Painting on the 60x60 map of a project with fifty objects dropped the
editor to 20 to 39 fps. A profile of a brush stroke showed four causes,
none of them the brush itself.

- Each frame of a stroke previews the model. The asset and hierarchy
  panels then built every row anew, so every label became a new text
  and a new upload to the GPU. One run spent 46 % of the main thread
  in those uploads. ListView.setItems now keeps a row whose item draws
  the same (sameListItem) and builds only the rows that changed.
- The brush drew the whole scene on every pointer event, on top of the
  preview. Now the preview draws what the stroke changed, once a frame.
  The rectangle tool asks for one drawing a frame for its box.
- An animated tile made the view draw in the tick and the preview drew
  it again in the same frame. animate now asks just before the frame
  is drawn and stays out when the view was drawn since the tick began.
- layoutSymbols ran on every drawing and costs up to the cube of the
  symbols. SymbolLayoutMemo keeps the spots while no anchor moves.
- A painted cell made the map read every "x,y" key again, and once
  more for each of the eight neighbours of every cell. layerCells reads
  a layer once per content into an index by place. layerTiles and the
  blocking cells take their neighbours from there (neighboursIn).
  parseCellKey reads a key without split, with the same results.

The test hook sceneRedraws counts how often the scene view was drawn.

Not done: a painted cell still works out the tiles and blocking cells
of the whole map again, so that part grows with the map.

Tests:
- Brush stroke on a copy of the project (stein2, Chrome): 20 to 39 fps
  before, 47.5 after, 55 to 57 without painting. Labels drawn again
  during the stroke 2012 before, none after. Scene drawings per frame
  1.32 before, 1 after.
- One painted cell, headless: 28 to 16 ms on 60x60, 109 to 49 ms on
  the same map doubled to 120x120.
- frame-preview: 2 new, red with the old pointer redraw.
- tilemap: 3 new (key reading, index, refresh), list-ping 1 new,
  symbol-layout 1 new. 5 single reversals turned each red.
- e2e 39,40 (melektaus-atx): ALL PASSED, 107 checks (1 new, a fast
  stroke: 6 drawings in 6 frames, no label drawn again). With the row
  reuse and the pointer redraw reverted it fails: 24 drawings in
  3 frames, and the panels draw their labels again.
- Gate (melektaus-atx): CHECK EXIT 0, 260 files, 4038 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:54:59 +02:00
adminandClaude Opus 5.5 2cf72022eb Ping an asset from its inspector link instead of selecting it (#221)
game-maker / gate (push) Successful in 2m52s
game-maker / suite (push) Successful in 9m2s
A single click on an asset link used to select the asset. That swapped
the inspector over to the asset, so the object being edited was gone
and the second click of a double-click landed on a different row. A
click now pings the asset in the asset panel, like Unity does in its
Project window, and a double-click opens it.

- state.pingAsset(id) emits a new `ping` event. It runs no command and
  leaves the selection alone, like openAsset.
- ListView.ping(id) draws an accent overlay on the row. It stays full
  for 200 ms and is gone after 1 s, driven by onFrame. destroy cancels
  the animation.
- The asset panel expands the group, scrolls to the row and pings it.
- The capture listener and followedLink in the inspector are gone.
  The inspector is no longer rebuilt, so pressCount on the label is
  enough. followsPress and pressOf are no longer exported from ui/.
- The "Asset" and "Part of" rows of a scene object were a ghost button
  that selected the asset. They are now a link label with the same
  ping and open behaviour, next to a read-only field with the name.
- The link logic lives in linkLabel() in fieldFactory.ts. createFieldRow
  and the asset row share it.
- TextField gets a readOnly option: no focus, no caret, no hover.
- New hook __gm.assetPing(). inspectorLink also reports the field
  next to the label (value, readOnly).

Findings:
- Renaming an asset while its object was selected left the old name
  in the inspector. This was already the case with the old button.
  The refresh now updates the name.

Tests:
- ./check.sh: 151 files, 2228 tests, CHECK EXIT 0 (before 150 / 2226).
  New: tests/ui/list-ping.test.ts for pingAlpha and pingAsset.
- e2e 1-16,28 on the final build: ALL PASSED, 575 checks.
  28l-ii has 9 checks instead of 5.
- Counter-checks, each failing exactly at its check: ping also selects,
  no follow-up frame (alpha stays 0.55), inspector never opens, field
  takes focus, name not refreshed, label not a link.
- Check total 1345, calculated. CI last counted 1336 at fd6af84.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 17:55:31 +02:00