diff --git a/Architecture.md b/Architecture.md index dfbfe7a..8461e00 100644 --- a/Architecture.md +++ b/Architecture.md @@ -119,7 +119,7 @@ web/index.html Vite source page (dev) index.html built page web/play.html a released game (#266) play.html built page (generated, served) src/main.ts, play.ts the two entries; page.ts is the canvas both are (the WebGL context, root, resize) src/core/model/ Project (object holders), Asset + AssetTypes, SceneObject (and what a list calls one: - `objectName`, `groupName`), Properties (value types, and the walks over a nested value: `mapNested`, a struct field taken out or renamed), 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:@`, 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)), tilemapMemo (what a map's cells work out to, kept while they hold the same: a version per cell map compared cell by cell, since strokes paint in place), 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), curve (#247: a drawn easing evaluated at t — each segment a cubic solved for t by bisection, held to its rules by `sanitizedCurve`: ends at 0 and 1, no point overtaking another, no handle past its neighbour — and which keys and `Lerp` nodes use one) + curvePresets (the built-in eases traced as curves, a segment halved only where it strays), graphLookup (what a graph sees of the project: behaviors to run, state machines to read, curves to ease along), structTypes (#253: Struct assets as types — every typed struct variable, struct field and `Pack`/`Expand` found and brought in line with its asset, a renamed field carried through every value first, the cycle rule), 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), renderLayers (#302: which cameras see an object — the project's named render layers, an object's own choice or its parent's, a camera's `Sees` and `Overlay`) + `objectName`, `groupName`), Properties (value types, and the walks over a nested value: `mapNested`, a struct field taken out or renamed), 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, and the nine-slice and sort line of any picture, #308), cutTarget (which picture a nine-slice or sort line is set on: a texture frame, or pixel art and vector art as a whole, #308), 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:@`, 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)), tilemapMemo (what a map's cells work out to, kept while they hold the same: a version per cell map compared cell by cell, since strokes paint in place), 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), curve (#247: a drawn easing evaluated at t — each segment a cubic solved for t by bisection, held to its rules by `sanitizedCurve`: ends at 0 and 1, no point overtaking another, no handle past its neighbour — and which keys and `Lerp` nodes use one) + curvePresets (the built-in eases traced as curves, a segment halved only where it strays), graphLookup (what a graph sees of the project: behaviors to run, state machines to read, curves to ease along), structTypes (#253: Struct assets as types — every typed struct variable, struct field and `Pack`/`Expand` found and brought in line with its asset, a renamed field carried through every value first, the cycle rule), 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), renderLayers (#302: which cameras see an object — the project's named render layers, an object's own choice or its parent's, a camera's `Sees` and `Overlay`) 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, clip (the region clip areas cut each object to, a convex polygon, #260) (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), joint (what it reads off a joint: its settings, where its far end is, its length and a hinge's limits, #154), 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; a cubic Bezier at `t` and cut in two at `t` — shared by vector art, its Boolean operations and the curve grips), color (`mixColor`, channel by channel — keys of an animation, stops of a gradient, the particles' Mix colour), recorder (#253: assignments taken back last first — the undo of an edit whose reach is not known in advance) 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 @@ -275,7 +275,7 @@ src/editor/inspector/ Inspector panel, host (what a section builds into, and `e every variable), shapeSection (the shapes of a vector drawing: the list, the four order buttons and the style of the picked one, #129; Fill type and Line type with the stop bar, the picked stop's rows or the texture, #186), portSection, aspectAction, - objectQueries/vectorRows/parentRow + objectQueries/vectorRows/parentRow, cutSection (the Nine-slice and Sorting rows, shared by the frame and the drawing inspectors, #308) src/editor/panels/ AssetPanel, assetGroups (groups by type and their order, #176), assetIcons (one SVG per asset type in icons/, shared by the panel, the + menu, the tabs and Scene objects, plus the List, Game, Plugins and User management tabs' own four, which stand for no asset), @@ -298,7 +298,7 @@ src/editor/graph/ GraphEditor (header, breadcrumb), GraphCanvas and what it 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) src/editor/container/ ContainerEditor (header), ContainerCanvas (a SceneViewport on a template) -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), +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, and the dashed nine-slice and sort lines of a drawing, #308), 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) 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), diff --git a/Development.md b/Development.md index 166f564..00d1bcd 100644 --- a/Development.md +++ b/Development.md @@ -18,7 +18,7 @@ php tests/php/accounts.test.php # the API's accoun # has and the web server's container has not (SKIP there) php tests/php/snapshots.test.php # the snapshot store (#231), the same way php tests/php/releases.test.php # the release store (#266), the same way -node tools/seed-e2e.mjs && node tools/e2e.mjs # 1731 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 1732 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/Pixel-Art.md b/Pixel-Art.md index 341db11..452ace4 100644 --- a/Pixel-Art.md +++ b/Pixel-Art.md @@ -16,8 +16,23 @@ new width and height and for the **anchor**: nine buttons for the corners, the e The picture keeps its place at that anchor, and whatever sticks out on the far side is cut off. A resize is one undo step, for every layer on every frame at once. -The inspector shows two rows: **Palette** (which palette the picture is painted in) and **Filter**, -**Nearest** by default so the pixels stay sharp when a sprite scales them up. +The inspector shows three rows: **Palette** (which palette the picture is painted in), **Filter**, +**Nearest** by default so the pixels stay sharp when a sprite scales them up, and **Nine-slice +scale** (see [below](#nine-slice-and-sort-line)). + +## Nine-slice and sort line + +A sprite wearing pixel art can be nine-sliced and given a sort line, exactly as a sprite wearing a +texture frame ([Textures](Textures#nine-slice--a-frame-that-keeps-its-corners)). The settings sit +on **the asset**, under *Nine-slice* and *Sorting* in its inspector, in canvas pixels. One set +serves **every frame**: the frames share the canvas size, and the frames of one animation want the +same corners and the same feet. + +- The tab draws the borders that are set as dashed lines and the sort line in yellow. They are not + dragged there, the painting tools own the canvas. Type the numbers in the inspector. +- With two frames or more, the asset itself names the strip of all frames side by side. That strip + is not sliced, only a single frame is. With one frame the asset and its frame are the same picture. +- Resizing the canvas keeps the numbers, and they are held inside the new size when drawn. ## Colours and the palette diff --git a/Textures.md b/Textures.md index 1630940..6865bd3 100644 --- a/Textures.md +++ b/Textures.md @@ -167,6 +167,11 @@ drawn twice as big beside a pattern at its old size reads as two different pictu sprite narrower than its borders applies to the scaled size: two 32-unit borders on a 20-unit box become two of 10. +**Drawings are sliced the same way (#308).** [Pixel art](Pixel-Art#nine-slice-and-sort-line) and +[vector art](Vector-Art#nine-slice-and-sort-line) carry the same borders, fill and sort line, set +on the asset as a whole and measured in canvas pixels, and they have a **Nine-slice scale** row of +their own. It is the same rule and the same inspector rows, only the target differs. + ## Sort line — where a figure stands On a tilemap layer sorted by Y (see [Tilemaps](Tilemaps#sorting-by-y)) a sprite is sorted by the @@ -183,6 +188,8 @@ box higher up, so a line 6 px up a 24 px frame lifts a 48-unit sprite by 12 unit so grab it by the knob; a line inside the frame can also be dragged directly. The inspector has the same number under *Sorting*. One drag or one typed value is one undo step. - 0 carries no key in the saved document. It only matters on a Z with a layer sorted by Y. +- Pixel art and vector art have the same row on the asset (#308). A drawing without frames is + measured against its whole canvas. **Fitting the sprite to the picture.** The *Width* and *Height* rows of a sprite carry a ↔ / ↕ button offering two things: **Fit to 64 x 48** sets that one side from the other and the picture's diff --git a/Vector-Art.md b/Vector-Art.md index ac5686d..b605a2a 100644 --- a/Vector-Art.md +++ b/Vector-Art.md @@ -307,6 +307,19 @@ Two differences to an uploaded picture, both from the picture path: a drawing ha (frames are rectangles cut out of a sheet, and there is no sheet), and it is **not stored** as an image — the project file holds the shapes, and the picture is rasterised again after a reload. +## Nine-slice and sort line + +A drawing can be nine-sliced and given a sort line, exactly as a texture frame +([Textures](Textures#nine-slice--a-frame-that-keeps-its-corners)), for a panel or a button drawn +with curves (#308). The settings sit on **the asset**, under *Nine-slice* and *Sorting* in its +inspector, in **canvas pixels**: a 16 px border of a 256 canvas is a sixteenth of it, whatever +resolution the picture is rasterised at. **Nine-slice scale** is a row of the asset, as on a +texture. + +The tab draws the borders that are set as dashed lines and the sort line in yellow, but they are +not dragged there: the arrow and the pen own the canvas. Type the numbers in the inspector. +Changing the canvas size keeps the numbers, and they are held inside the new size when drawn. + ## Known limits - **A texture fill always repeats.** Pixi turns a non-repeating picture fill into a repeating one,