Describe clip areas and On mouse wheel (#260)

- Concepts explains the clip area.
- Behaviors lists On mouse wheel and the type Clip area at the
  Properties node.
- Architecture names clip.ts.
- Development has the check sum 1549.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adminandClaude Opus 5.5 committed 2026-09-29 07:08:15 +02:00
1 parent 2e15bb21de
commit c86b7ba50e
4 files changed
+22 -5

No files matched your search

+1 -1
@@ -74,7 +74,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), 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)), 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)
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, 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), 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), 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
src/core/graph/ graph model, NodeRegistry/NodeContext/values (a travelling list may hold live objects, `storedList`
+5 -2
@@ -37,7 +37,7 @@ playing use the same two words.
hand under type *Any*.
`Properties` is the same node for the
object it is handed (fixed input `object`). Its **Type** setting, above the list, decides what
`+ Property` offers: *Sprite*, *Text*, *Collider*, *Camera* and *Container* offer their fields,
`+ Property` offers: *Sprite*, *Text*, *Collider*, *Camera*, *Container* and *Clip area* offer their fields,
*Behavior* the variables of the behavior picked below it (renaming such a variable carries the
port along, in any graph), and *Any* offers the kinds (Number, Text, …) and leaves the name to be
typed. Under *Sprite* the list goes on with the parameters of every shader in the project, since
@@ -164,7 +164,7 @@ playing use the same two words.
set to `a` also hears `A`, and a key picked with Shift held is stored lower-case. A key is let go
under the name it went down as, even when Shift changes in between (`1` down, `!` up).
- **Node set** (`src/core/graph/nodes/`, one file per node): events `On start`, `On enable`, `On update`, `On disable`, `On destroy` (see *Lifecycle*), `On key down/up/held`,
`On timer` (fires on the first frame past each due time; `late` says by how much, so `time - late` is exactly a multiple of the interval), `On collision enter/stay/exit` (stay every frame, or with an interval; while playing enter and stay tell normal, impulse and point of the contact), `On click` (the mouse pressed on the owner — anywhere when it has none), `On animation finished`, `On state entered`, `On state exited` (one output per state, see *State machines*), `Start` · flow `Branch`, `Sequence`, `Repeat`, `For each`, `Find` … `Match`, `Run behavior`, `End`, and the four that move or follow a state machine, `State branch`, `Set state`, `Set state by name`, `State transition` (see *State machines*) · data `Self`, `Owner`, `Parent`, `Object by name`, `Child by name` (the nearest object of that name below the given one: its children, then their children, and so on; within a level the first in hierarchy order, nothing when none is called so), `Name of`,
`On timer` (fires on the first frame past each due time; `late` says by how much, so `time - late` is exactly a multiple of the interval), `On collision enter/stay/exit` (stay every frame, or with an interval; while playing enter and stay tell normal, impulse and point of the contact), `On click` (the mouse pressed on the owner — anywhere when it has none), `On mouse wheel` (the wheel turned over the owner, or anywhere without one; `delta` in notches, positive downwards, a trackpad gives fractions), `On animation finished`, `On state entered`, `On state exited` (one output per state, see *State machines*), `Start` · flow `Branch`, `Sequence`, `Repeat`, `For each`, `Find` … `Match`, `Run behavior`, `End`, and the four that move or follow a state machine, `State branch`, `Set state`, `Set state by name`, `State transition` (see *State machines*) · data `Self`, `Owner`, `Parent`, `Object by name`, `Child by name` (the nearest object of that name below the given one: its children, then their children, and so on; within a level the first in hierarchy order, nothing when none is called so), `Name of`,
`Is asset` (is this object an instance of asset X — how you tell what you collided with),
and the plural lookups, each handing on a `list` of objects taken at that moment (destroyed
objects are never in it, switched-off ones are, as with the single lookups): `Objects by name`
@@ -381,6 +381,9 @@ playing use the same two words.
as one. A switched-off screen cannot swallow clicks. A behavior **without an owner** has no
shape that could be hit, so it takes every click inside the camera frame instead (the
`world x`/`world y` outputs say where) — that is the "click anywhere" listener.
`On mouse wheel` follows the same rule; what turned within one frame arrives as one `delta`,
one notch of a mouse wheel being 1. A part a clip area cuts off is never hit, by neither of
them nor by `Is hovered` (see [Concepts](Concepts)).
- **Idiomatic movement** (the demo's "Mover", five nodes): `On update → Move(Owner, dx = Axis
input.x, dy = Axis input.y, scale = speed, dt = On update.dt)`, `speed` being a `Variables` node.
- **Idiomatic platformer** (the example game's "Player"): `On update` adds `gravity · dt` to a
+15 -1
@@ -1,7 +1,7 @@
| Term | Meaning |
|---|---|
| **Account** | Who you are signed in as. The editor asks for a user name and a password before it loads anything, and every project belongs to one account — see [Accounts](Accounts). The **Account** menu is at the far right of the toolbar and holds the name, *Change password* and *Logout*; signing in and out changes what the canvas draws, it never reloads the page. |
| **Asset** | Named thing with a type (`scene`, `camera`, `sprite`, `text`, `behavior`, `collider`, `container`, `texture`, `animation`, `statemachine`, `shader`, `font`, `sound`, `particles`, `variables`) and typed properties. Assets have **no position**. |
| **Asset** | Named thing with a type (`scene`, `camera`, `clip`, `sprite`, `text`, `behavior`, `collider`, `container`, `texture`, `animation`, `statemachine`, `shader`, `font`, `sound`, `particles`, `variables`) and typed properties. Assets have **no position**. |
| **Texture** | An uploaded image. Scenes, textures, animations, state machines, shaders, fonts, sounds and Variables assets are the eight types that cannot be placed: a texture has no position, it is *worn* by a sprite through the ordinary property `texture`. See [Textures](Textures). |
| **Font** | An uploaded typeface, worn by a text through the ordinary property `font`; no font means the editor's own. Uploaded and picked exactly like a texture, and stored the same way. See [Fonts](Fonts). |
| **Sound** | An uploaded audio file. Uploaded, picked and stored exactly like a typeface — but nothing *wears* it: it is neither on screen nor in the scene, and a graph plays it with `Play sound`. Its own rows say how loud it is and whether it loops; the node scales the one and can overrule the other either way. See [Sounds](Sounds). |
@@ -39,6 +39,20 @@ one, so switching it off hands the view to the next; with none on the tab stays
shows what Play would show, minus the editor symbols. Play has no built-in behaviour (no input,
no movement): everything that happens is defined by behavior graphs.
**A clip area cuts what is below it** (#260). It is an object of its own (*Clip area*, `+`
menu) with a `width` x `height`, and it turns, scales and mirrors with its parent like a sprite.
Everything parented below it, at any depth, is drawn only inside its rectangle, in the Scene tab
as in the game, and a click or hover on the part it cuts off hits nothing (`On click`,
`Is hovered`, `On mouse wheel`). Clip areas above one another intersect. In the game the area
itself is invisible; the Scene tab draws it as a dashed outline, which the eye hides under
*Shape* and which is also where it is grabbed, so a click inside still reaches its content.
While an object, or anything above it, is **selected** (the area itself, one row of a list, the
window around the area), the Scene tab shows its cut-off part faintly if it is a sprite or a
text, and it can be grabbed there. That is
how content that scrolled out of view is found again. Tilemaps and particles below an area are
cut the same way, only without that faint rest. A list that scrolls is a clip area with the list
below it, moved by a graph, for example from `On mouse wheel`.
**Game view scale** (#225). The picker in the Game tab's header sets how large the camera's
picture (its `width` x `height`) is drawn:
+1 -1
@@ -15,7 +15,7 @@ npm run build # writes dist/ and regenerates index.html
php tools/make-user.php <name> <password> [admin|user] # an account; every tool signs in (see Accounts)
php tests/php/accounts.test.php # the API's account rules, no server needed (CI's gate job)
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1544 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1549 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