Files
feuerwerk/src/editor/graph
adminandClaude Opus 5.5 6d79cf59a3
game-maker / gate (push) Successful in 2m44s
game-maker / suite (push) Successful in 13m55s
Move a large graph instead of drawing it again (#292)
In a graph of many nodes the frame rate dropped while panning, and
more so while one node was dragged. Every pointer move rebuilt every
box, every text and every curve, and a drag also announced a changed
project, so the panels rebuilt along with it.

- Panning and zooming move the picture. GraphCanvas.applyView sets
  position and scale and draws anew only the grid and the rubber
  band. It used to call redraw().
- A node draws its box and makes its texts only when what they show
  has changed. NodeView keeps a signature of what redraw reads and
  one of what rebuildTexts reads, and returns early while they hold.
- A drag does not announce a changed project. GraphDrags writes the
  model on every pointer move and asks the canvas once a frame to
  follow (GraphCanvasHost.moved). state.preview() waits for the
  command of the release.
- Nodes outside the picture are not drawn. inView in graphView.ts is
  the rule, cull() applies it after every redraw and every change of
  the view.
- The graph is a render group, and box and pins go into the batch.
  The mask sits on a container above the group, on the group itself
  it would be panned and zoomed along.
- The rubber band and the drop mark of a dragged behavior are drawn
  on their own (drawBand), without a redraw of the graph.

Measured in the CI image with 388 nodes and 540 links, fitted to the
canvas, 240 pointer moves 16 ms apart:

- Pan, script per move: 25.2 ms before, 2.0 ms after
- Pan: 4.4 frames per second before, 18.7 after
- Drag a node: 2.7 frames per second before, 22.4 after
- The still picture: 9 frames per second before, 21 after

Not solved: the still picture of such a graph stays at 21 frames per
second in the test browser. What is left is the drawing itself, and
the frame rates are those of that browser, not of a desktop GPU.

Tests:
- Gate on melektaus-atx: 207 files, 3121 tests (3114 + 7), exit 0
- e2e 4,6,18,19,20,23,24,26,28,31,36,43,51,53 on melektaus-atx: 542
  pass, 1 fail. The fail is module 51 after module 43, an order the
  suite does not have, and it fails the same way without this
  change. Module 51 alone: 12 checks, all pass.
- No full run and no smokes. The sum of 1660 (1656 + 4) is reckoned,
  and the CI workflow is switched off.
- Seven unit tests: six for inView in tests/editor/graph-view.test.ts
  and one in frame-preview.test.ts
- Four e2e checks in block 6z-xii of module 06: pan, drag, zoom in
  and fit, a changed value
- Seven browser counter-probes fail 2 to 3 checks each

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 10:18:20 +02:00
..
Refactoring round 5 covers the code since round 4 without changing behaviour: four identical copies of dot() and three of "nearest point on a segment" stood in the collision math, in the hit area of the collider outlines and in the polygon handles, so they moved into the new module src/core/util/vec.ts; the warning line, the busy state, info() and the caret reset were written out line by line in both the sign-in screen and the password dialog and are now FormStatus; the closing row "Cancel plus a confirming button, optionally one on the left" was built by hand in FormDialog, FilePicker, OpenProjectDialog and PasswordDialog and is now dialogButtons(); the header bar was drawn by the toolbar, the TabHeader and the Breadcrumb each on its own and is now drawHeaderBar(); AddColliderCommand and AddRigidbodyCommand share a base, each subclass only builds its own asset; Editor.ts derives the panes from assetEditors instead of repeating eight entries and clamps its splitters with clamp(); jscpd over src falls from 0.19 % to 0.14 %; dead code is gone - listScenes() has been orphaned since the Scene picker fell away (#183), DEFAULT_FILTER (#152) was never used, the two test hooks projectPickerRowAt/rowPosition and particleCompiles are read by no tool, and four functions lost an export they did not need; seven comments that told history ("used to", "no longer", "since #...") describe the state of things now, and that this changed nothing was proved by a rebuild - the bundle is md5 identical, b4ad0dfe... before and after; the README said Logout sits at the far right of the toolbar, which has been the Account menu since #182, and wiki/Architecture.md was missing src/core/util/ altogether; 4 new unit tests cover vec.ts, and switching the clamp on the segment off makes exactly one of them fail while none of the 76 neighbouring tests notice, so that clamping was covered nowhere before (#85)
2026-09-20 17:24:42 +02:00