Architecture catches up with refactoring round 6 (#85)

- Architecture names SheetCanvas, mixColor, fingerprint, MoveCommand
  and rayOf, plus seven modules that were missing, among them
  vectorCurves, portTypes, SortableList and PixelThumbs. The Scope
  entry is current again after #164.
- Scene editing no longer points to symbol-icons.test.ts, which went
  into svg-icons.test.ts with #176.
- Development: the editor check sum is 1310. CI measured 1308 at
  d7c0b7c, plus the two new pan checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adminandClaude Opus 5.5 committed 2026-09-23 06:58:00 +02:00
1 parent 9087225e9f
commit db8b6428d3
3 files changed
+10 -9

No files matched your search

+8 -7
@@ -72,14 +72,15 @@
``` ```
web/index.html Vite source page (dev) index.html built page (generated, served) web/index.html Vite source page (dev) index.html built page (generated, served)
src/core/model/ Project (object holders), Asset + AssetTypes, SceneObject, Properties (value types), hierarchy, walk (generic parent/child walks), instance (container content resolved from its template), usages (where an asset is used), container (the cycle guard), placement (what may be dropped where), texture (frames, the slice grid, a frame's collision outlines), frameOutline (#193: a frame's outlines as a collider wears them, centred, a pixel to a unit, cut into pieces once per drawn list), traceCollision (#161: a frame's outlines read off its picture — the pixels from an alpha threshold on are solid, each 4-connected island is walked round along the pixel edges and cut down to a few corners without ever crossing itself; crumbs below 1 % of the frame drop out), generated (pictures that are drawn rather than uploaded, #185: the key `gen:<assetId>@<revision>` and the register of readers that tell the picture path an asset's canvas size and revision), vectorart (#129: the canvas as a property, which ring is worth drawing, and the revision as a fingerprint of the drawing rather than a counter, a texture fill's picture included) + vectorPath (what a shape draws, as plain commands: closed rings fill, every ring strokes, a segment is a line while neither of its ends carries a handle; a paint resolved to sorted stops or the picture it names) + vectorPaint (#186: gradients and texture fills — where a paint lies when it is switched on, the colour between two stops, adding, moving and removing a stop, a paint moved with its shape, and the rule that a texture fill takes uploaded pictures only) + vectorBoolean (#187: union, subtract, intersect and exclude on the sampled outlines, each shape read by the even-odd rule; the result rings in the order Pixi's hole detection needs, every outline followed by its holes and preceded by the islands inside them), pixelart (#130: the palette a picture is painted in, how the layers of a frame come together, the sheet of all frames, a frame id read as a cut of it, and the revision) + pixelCel (the file of one layer on one frame, and its SHA-256 name worked out in the browser) + pixelDraw (what the tools do to the indices: brush, line, rectangle, ellipse, fill, resize about an anchor, merge, a palette colour taken out) + pixelEdit (every edit of layers, frames and cels as a function from one state to the next), polygon (an outline checked, cut into convex pieces and clipped to a rectangle), tile (the three kinds and their block shapes, reading a tile's pictures, the animation step), autotile (which quarter tile a neighbourhood asks for, the 47/16 tiles a block produces, 1 for a plain tile), tilemap (the cells of a layer, which neighbours a cell is joined to, the cells a stroke or a rectangle covers), tilemapCollision (the solid cells of a map, drawn in or out by their tile's collision scale and merged into rectangles, one group per one-way angle and per surface (`tileMaterials`, #193), the outlined cells as polygons — an autotile's outlines cut into its quarters and pieced together per cell like its picture —, where one sits in the world, and which cells of a placed map a world rectangle can reach, in cells (`cellsWithin`, #184)), animation (which frame at time t, a row's value there, what a row may aim at, the players on an object; KeyRef and its lookups) + animationPreview (the root at a frame, written into copies), graphLookup (what a graph sees of the project: behaviors to run, state machines to read), Scope (where a state machine's current state lives: per instance or one for the run — variables are shared by living on a Variables asset instead), collisionLayers (which colliders may meet: the project's named layers, a collider's layer and mask, and the one rule `layersMeet` the engine, Solids and the event pair search all answer by) src/core/model/ Project (object holders), Asset + AssetTypes, SceneObject, Properties (value types), hierarchy, walk (generic parent/child walks), instance (container content resolved from its template), usages (where an asset is used), container (the cycle guard), placement (what may be dropped where), texture (frames, the slice grid, a frame's collision outlines), frameOutline (#193: a frame's outlines as a collider wears them, centred, a pixel to a unit, cut into pieces once per drawn list), traceCollision (#161: a frame's outlines read off its picture — the pixels from an alpha threshold on are solid, each 4-connected island is walked round along the pixel edges and cut down to a few corners without ever crossing itself; crumbs below 1 % of the frame drop out), generated (pictures that are drawn rather than uploaded, #185: the key `gen:<assetId>@<revision>`, the register of readers that tell the picture path an asset's canvas size and revision, and the `fingerprint` pixel art and vector art make their revision with), vectorart (#129: the canvas as a property, which ring is worth drawing, and the revision as a fingerprint of the drawing rather than a counter, a texture fill's picture included) + vectorPath (what a shape draws, as plain commands: closed rings fill, every ring strokes, a segment is a line while neither of its ends carries a handle; a paint resolved to sorted stops or the picture it names) + vectorPaint (#186: gradients and texture fills — where a paint lies when it is switched on, the colour between two stops, adding, moving and removing a stop, a paint moved with its shape, and the rule that a texture fill takes uploaded pictures only) + vectorBoolean (#187: union, subtract, intersect and exclude on the sampled outlines, each shape read by the even-odd rule; the result rings in the order Pixi's hole detection needs, every outline followed by its holes and preceded by the islands inside them) + vectorCurves (#208: every sampled point remembers its cubic and its `t`, so a run of result points along one cubic becomes that cubic again, cut with de Casteljau), pixelart (#130: the palette a picture is painted in, how the layers of a frame come together, the sheet of all frames, a frame id read as a cut of it, and the revision) + pixelCel (the file of one layer on one frame, and its SHA-256 name worked out in the browser) + pixelDraw (what the tools do to the indices: brush, line, rectangle, ellipse, fill, resize about an anchor, merge, a palette colour taken out) + pixelEdit (every edit of layers, frames and cels as a function from one state to the next), polygon (an outline checked, cut into convex pieces and clipped to a rectangle), tile (the three kinds and their block shapes, reading a tile's pictures, the animation step), autotile (which quarter tile a neighbourhood asks for, the 47/16 tiles a block produces, 1 for a plain tile), tilemap (the cells of a layer, which neighbours a cell is joined to, the cells a stroke or a rectangle covers), tilemapCollision (the solid cells of a map, drawn in or out by their tile's collision scale and merged into rectangles, one group per one-way angle and per surface (`tileMaterials`, #193), the outlined cells as polygons — an autotile's outlines cut into its quarters and pieced together per cell like its picture —, where one sits in the world, and which cells of a placed map a world rectangle can reach, in cells (`cellsWithin`, #184)), animation (which frame at time t, a row's value there, what a row may aim at, the players on an object; KeyRef and its lookups) + animationPreview (the root at a frame, written into copies), graphLookup (what a graph sees of the project: behaviors to run, state machines to read), Scope (how long a shared value lives: per instance, one for the run, or one per scene and rebuilt with every scene that loads, #164 — for a state machine's current state and for the values of a Variables asset), collisionLayers (which colliders may meet: the project's named layers, a collider's layer and mask, and the one rule `layersMeet` the engine, Solids and the event pair search all answer by)
src/core/properties/ PropertySchema, kinds (one row per value kind), listItems (an item's kind, read off its value), resolve (the only override merge), deviation (what is gold), collider/camera/bounds geometry (with the side a one-way collider blocks from, and the rectangle around a shape a broad phase looks at first, #184), convex (capsules and polygons: rounded convex pieces against each other), ray (where a ray meets a shape, in double precision), rigidbody (what the engine reads off a rigidbody, a collider's material and the scene), aspect, enabled, editorRun, assetRef/textureRef (how a reference reads), declaredRows (the row a Property node declares in a shader or particle graph, and the params that node has in both) src/core/properties/ PropertySchema, kinds (one row per value kind), listItems (an item's kind, read off its value), resolve (the only override merge), deviation (what is gold), collider/camera/bounds geometry (with the side a one-way collider blocks from, and the rectangle around a shape a broad phase looks at first, #184), convex (capsules and polygons: rounded convex pieces against each other), ray (where a ray meets a shape, in double precision), rigidbody (what the engine reads off a rigidbody, a collider's material and the scene), aspect, enabled, editorRun, assetRef/textureRef (how a reference reads), declaredRows (the row a Property node declares in a shader or particle graph, and the params that node has in both)
src/core/util/ list (take out, put back and move an item — what a command's undo is made of), vec (dot, the closest point on a segment — shared by the collider maths, the outline hit area and the polygon grips) src/core/util/ list (take out, put back and move an item — what a command's undo is made of), vec (dot, the closest point on a segment — shared by the collider maths, the outline hit area and the polygon grips), color (`mixColor`, channel by channel — keys of an animation, stops of a gradient, the particles' Mix colour)
src/core/commands/ undoable commands (pixelArtCommands: one command runs any pixel art edit and keeps the state before it, #130), CommandStack, SetBagValueCommand base, RenameCommand base (undone by renaming back: variable, struct field, port), one import command shape for texture/font/sound, require.ts (validated lookups, and what an instance may not change), naming.ts src/core/commands/ undoable commands (pixelArtCommands: one command runs any pixel art edit and keeps the state before it, #130), CommandStack, SetBagValueCommand base, RenameCommand base (undone by renaming back: variable, struct field, port), MoveCommand base (undone by moving back: tile picture, tilemap layer, vector shape), vectorArtCommands (#129: the shapes of a drawing, one gesture one command), one import command shape for texture/font/sound, require.ts (validated lookups, and what an instance may not change), naming.ts
src/core/graph/ graph model, NodeRegistry/NodeContext/values (a travelling list may hold live objects, `storedList` src/core/graph/ graph model, NodeRegistry/NodeContext/values (a travelling list may hold live objects, `storedList`
narrows one down to what a PropertyBag may hold, #157), interpreter, dropTarget, nested (behaviors as nodes), narrows one down to what a PropertyBag may hold, #157), interpreter, dropTarget, nested (behaviors as nodes),
emitGraph (the walk both graph compilers share: each node once, in dependency order; cycles and property names reported), emitGraph (the walk both graph compilers share: each node once, in dependency order; cycles and property names reported),
sharedState (what a run shares: a bag per Variables asset, the state of a global machine), sharedState (what a run shares: a bag per Variables asset, the state of a global machine; what a scene change carries forward and what it starts afresh, #164),
portTypes (#207: ports of one node that carry the same value, and the type their inputs agree on),
savedValues (#166: the SaveArea a run reads persistent Variables assets from and writes them to, and restoring a save through today's declaration), savedValues (#166: the SaveArea a run reads persistent Variables assets from and writes them to, and restoring a save through today's declaration),
stateMachine (the State node, a machine's states, the ports they become), variablePorts, propertyPorts, stateMachine (the State node, a machine's states, the ports they become), variablePorts, propertyPorts,
lookup (what a node may look up: behaviors, state machines), keyRepeat; nodes/{events,flow,data,action,variable}/<Name>.ts lookup (what a node may look up: behaviors, state machines), keyRepeat; nodes/{events,flow,data,action,variable}/<Name>.ts
@@ -105,7 +106,7 @@ src/runtime/physics/ engine (loads Rapier once, reports its state, converts be
normal, impulse and point; whether a dynamic body lands on or passes a one-way collider, normal, impulse and point; whether a dynamic body lands on or passes a one-way collider,
decided before each step for the contact hook; the push a `Move` gives a dynamic body, and decided before each step for the contact hook; the push a `Move` gives a dynamic body, and
what the physics nodes reach through `NodeContext.physics`) what the physics nodes reach through `NodeContext.physics`)
src/ui/ widget toolkit (generic, knows nothing about assets) src/ui/ widget toolkit (generic, knows nothing about assets); SortableList + sortable (the layer list of every editor that has one: rows dragged into order, eye, duplicate, cross, rename in place; the index arithmetic of a list shown upside down, kept apart so it is measured without a canvas)
src/viewport/ view (transforms), items (what to draw), symbols (how to draw it), src/viewport/ view (transforms), items (what to draw), symbols (how to draw it),
symbolIcons (the SVG files in icons/, parsed once, in the theme's colours, #175), symbolIcons (the SVG files in icons/, parsed once, in the theme's colours, #175),
FileLibrary (load once, never retry a failure, tell the listeners) ← TextureLibrary, FontLibrary; FileLibrary (load once, never retry a failure, tell the listeners) ← TextureLibrary, FontLibrary;
@@ -175,11 +176,11 @@ src/editor/graph/ GraphEditor (header, breadcrumb), GraphCanvas, graphView
AnnotationView + annotationDrag (groups and comments: what a drag carries, each thing moved once), AnnotationView + annotationDrag (groups and comments: what a drag carries, each thing moved once),
SnapToggle (the magnet every tab that snaps carries, the vector art tab included, #194) SnapToggle (the magnet every tab that snaps carries, the vector art tab included, #194)
src/editor/container/ ContainerEditor (header), ContainerCanvas (a SceneViewport on a template) src/editor/container/ ContainerEditor (header), ContainerCanvas (a SceneViewport on a template)
src/editor/texture/ TextureEditor (header), TextureCanvas (picture + frames), SliceDialog (a FormDialog), GenerateCollisionDialog (#161: the rows, and a summary that traces while the numbers change; the texture library hands it the sheet's pixels), sheetView (the grid maths), src/editor/texture/ SheetCanvas (the shell of the Texture, Pixel art and Vector art canvases: ground, clip, hint, a middle or Shift drag that pans, wheel zoom, Fit and the view each document keeps), TextureEditor (header), TextureCanvas (picture + frames), SliceDialog (a FormDialog), GenerateCollisionDialog (#161: the rows, and a summary that traces while the numbers change; the texture library hands it the sheet's pixels), sheetView (the grid maths),
ImagePicker + imageGrid (the "+ → Texture" dialog), checker (the transparency board) ImagePicker + imageGrid (the "+ → Texture" dialog), checker (the transparency board)
src/editor/pixelart/ PixelArtEditor (header: Resize…), PixelArtCanvas (one frame composed as the picture path composes it, src/editor/pixelart/ PixelArtEditor (header: Resize…), PixelArtCanvas (one frame composed as the picture path composes it,
whole zoom steps, grid, onion skin and tile preview; a stroke paints a copy and becomes one command), whole zoom steps, grid, onion skin and tile preview; a stroke paints a copy and becomes one command),
PixelArtSide (tools, palette, layers, frames, view, preview), PaletteGrid, PixelPreview, ResizeCanvasDialog, PixelArtSide (tools, palette, layers, frames, view, preview), toolOptions (#201: the options that change what a tool paints), PixelThumbs (the row pictures of the layer and frame lists, repainted only when their key changes), PaletteGrid, PixelPreview, ResizeCanvasDialog,
pixelActions (what the panel does; merge and resize work out the new cels), pixelView (zoom steps, the pixel pixelActions (what the panel does; merge and resize work out the new cels), pixelView (zoom steps, the pixel
under the pointer), celUploadStore (the project store that uploads the cels before it saves) under the pointer), celUploadStore (the project store that uploads the cels before it saves)
src/editor/vectorart/ VectorArtEditor (header: the three tools, the picked point's type or, with Paint, whose handles, and the magnet), VectorArtCanvas (the drawing src/editor/vectorart/ VectorArtEditor (header: the three tools, the picked point's type or, with Paint, whose handles, and the magnet), VectorArtCanvas (the drawing
+1 -1
@@ -13,7 +13,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
npm run build # writes dist/ and regenerates index.html npm run build # writes dist/ and regenerates index.html
./build.sh # the same under `set -o pipefail`, for callers that pipe the output ./build.sh # the same under `set -o pipefail`, for callers that pipe the output
php tools/make-user.php <name> <password> # an account; every tool signs in (see Accounts) php tools/make-user.php <name> <password> # an account; every tool signs in (see Accounts)
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1307 editor checks, screenshots in /tmp/gm-e2e-*.png node tools/seed-e2e.mjs && node tools/e2e.mjs # 1310 editor checks, screenshots in /tmp/gm-e2e-*.png
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
./e2e.sh start [GM_STEPS] # the same run detached, see below ./e2e.sh start [GM_STEPS] # the same run detached, see below
./e2e.sh status # live progress, or the last run's result ./e2e.sh status # live progress, or the last run's result
+1 -1
@@ -21,7 +21,7 @@ source each have one in `src/viewport/icons/`, bundled with the editor and parse
draws in the symbol's own units with the origin at its centre (the `viewBox` is centred on it, so draws in the symbol's own units with the origin at its centre (the `viewBox` is centred on it, so
the file looks the same in any SVG viewer), and `currentColor` stands for the colour the theme the file looks the same in any SVG viewer), and `currentColor` stands for the colour the theme
gives that symbol. To change an icon, edit its file and build. Pixi's SVG parser is not a browser, gives that symbol. To change an icon, edit its file and build. Pixi's SVG parser is not a browser,
so the files keep to what both draw alike, and `tests/viewport/symbol-icons.test.ts` holds them to so the files keep to what both draw alike, and `tests/ui/svg-icons.test.ts` holds them to
it: only `path`, `circle`, `rect`, `ellipse` and `line` (Pixi reads `polygon` points as whole it: only `path`, `circle`, `rect`, `ellipse` and `line` (Pixi reads `polygon` points as whole
numbers), no `transform` (ignored), every shape states its `fill` (a browser fills a shape without numbers), no `transform` (ignored), every shape states its `fill` (a browser fills a shape without
one black, Pixi does not), colours as `#rrggbb`, `none` or `currentColor`. What stays code is what one black, Pixi does not), colours as `#rrggbb`, `none` or `currentColor`. What stays code is what