From 56440145f73672dc351d75c95fe6a64c8e07ddd8 Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Sun, 20 Sep 2026 20:51:57 +0200 Subject: [PATCH] Vector art is drawn into a picture (#129, stage 2): Textures says that a drawn picture is rasterized at twice the canvas resolution and that the canvas is the frame - what juts out over it is not in the picture; Architecture names vectorart, core/model/vectorPath and viewport/vectorArtPicture; Development carries the check sum 1165 --- Architecture.md | 5 ++++- Development.md | 2 +- Textures.md | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Architecture.md b/Architecture.md index 36280d0..ac959d4 100644 --- a/Architecture.md +++ b/Architecture.md @@ -68,7 +68,7 @@ ``` 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), generated (pictures that are drawn rather than uploaded, #185: the key `gen:@` and the register of readers that tell the picture path an asset's canvas size and revision), 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, 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), generated (pictures that are drawn rather than uploaded, #185: the key `gen:@` 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) + 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), 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, 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/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/commands/ undoable commands, 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 @@ -108,6 +108,9 @@ src/viewport/ view (transforms), items (what to draw), symbols (how to under its revision key, the older one freed when the newer is drawn; who draws which asset type, and the factory that looks an asset up in the open project) — no GPU, so it is measured without a browser, + vectorArtPicture (the rasteriser of #129: the draw commands of + core/model/vectorPath painted onto a render texture of the canvas size, at twice its + resolution; registers vector art in both halves of the picture path), SoundLibrary, ShaderLibrary, ParticleLibrary, particles (one ParticleContainer per source), tilemap (one container per layer), drawOrder (objects and tilemap layers by z, #174), activeCamera — no editor concepts, diff --git a/Development.md b/Development.md index 237a196..85399e3 100644 --- a/Development.md +++ b/Development.md @@ -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 ./build.sh # the same under `set -o pipefail`, for callers that pipe the output php tools/make-user.php # an account; every tool signs in (see Accounts) -node tools/seed-e2e.mjs && node tools/e2e.mjs # 1157 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 1165 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 ./e2e.sh start [GM_STEPS] # the same run detached, see below ./e2e.sh status # live progress, or the last run's result diff --git a/Textures.md b/Textures.md index b5f416e..5692517 100644 --- a/Textures.md +++ b/Textures.md @@ -185,6 +185,11 @@ sheet, and a drawn picture has none to cut from. And it is **not stored**: nothi reload. The whole path is the same one an uploaded file takes, which is why a drawn picture works in shaders, particles, tiles and tilemaps without any of them knowing about it. +A drawn picture is rasterised at **twice** the resolution of its canvas, so zooming into it does +not turn to mush at once; what a sprite is measured by stays the canvas size. The canvas is also +the frame: whatever a shape reaches past its edge is not in the picture, which is what makes the +size a sprite shows the size one sees. + **Limits.** nginx caps request bodies at 1 MB, so the editor shrinks images over 2048 px per side and re-encodes to WebP when they are still too big — but an image that already fits is uploaded byte for byte, because re-encoding pixel art would destroy it. Anything still too