@pixerate/editor 0.271.0 → 0.272.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation-editor/index.cjs +60 -60
- package/dist/animation-editor/index.js +4 -4
- package/dist/brushes/index.cjs +69 -66
- package/dist/brushes/index.js +6 -3
- package/dist/brushes/patch.d.cts +1 -1
- package/dist/brushes/patch.d.ts +1 -1
- package/dist/brushes/schema.d.cts +1 -0
- package/dist/brushes/schema.d.ts +1 -0
- package/dist/brushes/types.d.cts +8 -0
- package/dist/brushes/types.d.ts +8 -0
- package/dist/{brushstrokeRender-WR2N5HHY.cjs → brushstrokeRender-5YBCLFDQ.cjs} +15 -15
- package/dist/{brushstrokeRender-A727TTNQ.js → brushstrokeRender-DZGFU3J4.js} +3 -3
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-YNFSH72F.js → chunk-2F3YDXCN.js} +1 -1
- package/dist/{chunk-QYXUE37Q.js → chunk-2XDNF73E.js} +1 -1
- package/dist/{chunk-3KNQ2W6X.cjs → chunk-3JKCREEU.cjs} +59 -53
- package/dist/{chunk-B5W677L7.js → chunk-5HP2VSAS.js} +1 -1
- package/dist/{chunk-BPJSI4NT.cjs → chunk-7W2EQQBP.cjs} +2 -2
- package/dist/{chunk-LETF75CA.js → chunk-CLB2I2FU.js} +1 -1
- package/dist/{chunk-BAZMCFVL.js → chunk-DZVRH63Y.js} +1 -1
- package/dist/{chunk-U2ASNGO6.cjs → chunk-FXVCB6YG.cjs} +35 -35
- package/dist/{chunk-EU2ZZA6L.cjs → chunk-GHGBIAWQ.cjs} +126 -39
- package/dist/{chunk-2WOGXEDX.cjs → chunk-M3RZOF3G.cjs} +1 -1
- package/dist/{chunk-GSTSZPSR.js → chunk-N3SKPQEH.js} +225 -18
- package/dist/{chunk-J5VQYK7T.cjs → chunk-N5IMDAHM.cjs} +251 -44
- package/dist/{chunk-ININNHLM.js → chunk-NAHJV3O6.js} +11 -5
- package/dist/{chunk-JJ2H25JG.cjs → chunk-SNAFFCAX.cjs} +200 -174
- package/dist/{chunk-M2ZVPU7L.cjs → chunk-TNLKFW7D.cjs} +23 -23
- package/dist/{chunk-KZI3YWKW.js → chunk-UXYCY3HP.js} +93 -6
- package/dist/{chunk-DDL3ZBHK.cjs → chunk-YJANF2BL.cjs} +86 -86
- package/dist/{chunk-TNHDCP4R.js → chunk-ZEI7ZEA4.js} +31 -5
- package/dist/image-editor/index.cjs +789 -789
- package/dist/image-editor/index.js +5 -5
- package/dist/paint/index.cjs +2 -2
- package/dist/paint/index.js +1 -1
- package/dist/paint/wet/world.d.cts +37 -1
- package/dist/paint/wet/world.d.ts +37 -1
- package/dist/paint-editor/brush-controls.d.cts +2 -0
- package/dist/paint-editor/brush-controls.d.ts +2 -0
- package/dist/paint-editor/brush-model.d.cts +14 -1
- package/dist/paint-editor/brush-model.d.ts +14 -1
- package/dist/paint-editor/index.cjs +343 -306
- package/dist/paint-editor/index.js +48 -11
- package/dist/paint-editor/ui.d.cts +1 -1
- package/dist/paint-editor/ui.d.ts +1 -1
- package/dist/paint-editor/wet.d.cts +8 -1
- package/dist/paint-editor/wet.d.ts +8 -1
- package/dist/vector/index.cjs +999 -999
- package/dist/vector/index.js +5 -5
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +1 -0
- package/skills/pixerate-paint-editor/SKILL.md +4 -11
- package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
- package/skills/pixerate-paint-editor/references/ghost.md +47 -0
- package/skills/pixerate-paint-watercolour/SKILL.md +1 -0
package/dist/vector/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
traceField,
|
|
36
36
|
traceVectorImage,
|
|
37
37
|
vectorTraceContours
|
|
38
|
-
} from "../chunk-
|
|
38
|
+
} from "../chunk-2F3YDXCN.js";
|
|
39
39
|
import {
|
|
40
40
|
rasterizeCoverage
|
|
41
41
|
} from "../chunk-ADMRNWR7.js";
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
reverseMorphContour,
|
|
67
67
|
subpathToMorphContour,
|
|
68
68
|
turnMorphContour
|
|
69
|
-
} from "../chunk-
|
|
69
|
+
} from "../chunk-2XDNF73E.js";
|
|
70
70
|
import {
|
|
71
71
|
DEFAULT_VECTOR_FONT,
|
|
72
72
|
IDENTITY_MATRIX,
|
|
@@ -556,10 +556,10 @@ import {
|
|
|
556
556
|
withVectorStrokes,
|
|
557
557
|
withVectorTargetPaint,
|
|
558
558
|
zigzagPaths
|
|
559
|
-
} from "../chunk-
|
|
559
|
+
} from "../chunk-ZEI7ZEA4.js";
|
|
560
560
|
import {
|
|
561
561
|
snapshotBrushLibrary
|
|
562
|
-
} from "../chunk-
|
|
562
|
+
} from "../chunk-UXYCY3HP.js";
|
|
563
563
|
import "../chunk-JL6YH5WD.js";
|
|
564
564
|
import {
|
|
565
565
|
createProvenance
|
|
@@ -597,7 +597,7 @@ import {
|
|
|
597
597
|
resolveEffectValues
|
|
598
598
|
} from "../chunk-MV7CYFMJ.js";
|
|
599
599
|
import "../chunk-V2ZCJRDM.js";
|
|
600
|
-
import "../chunk-
|
|
600
|
+
import "../chunk-N3SKPQEH.js";
|
|
601
601
|
import "../chunk-W6JDUXP3.js";
|
|
602
602
|
import {
|
|
603
603
|
GRAIN_PATTERNS
|
package/package.json
CHANGED
|
@@ -20,6 +20,7 @@ built-in presets (read-only) and the user's brushes, shared by every editor that
|
|
|
20
20
|
| Dynamics | Pen feel: pressure to size and opacity, smoothing, tilt, velocity, jitter (`sizeJitter`, `angleJitter` for rotation, `opacityJitter`, `scatter`), rotation, `count` (dabs per spacing step, each jittered) and `flip` (mirror dabs at random: `x`, `y`, `xy`). |
|
|
21
21
|
| Behaviour | `surface` `dry`, `wet` (`wet` settings) or `thick` (`thick` impasto settings); paper `grain`; `exchange` (pick-up and mix; a `reservoir` makes a Mixer Brush); tool `strength`. |
|
|
22
22
|
| Light | Light the brush gives off (`amount`), plus suggested layer `spill` and `glow`. |
|
|
23
|
+
| Ghost | On wet paint (`behaviour.surface: "wet"`): `linger` (0.5..60 s before the brush's own colour fades away) and `smear` (0..1, how much it lifts and drags the paint it crosses). Presets `ghost-wash`, `ghost-gouache`, `ghost-oil` and `invisible-ink`. |
|
|
23
24
|
| Motion | Animation after painting (live effect paint, particle `waveSpeed`). |
|
|
24
25
|
| Colour | A `default` colour, a `palette` of up to 16, `own` (always its own colour). Each is a hex or `rgba()` colour, a light / dark pair `{ light, dark }`, a gradient or effect paint. A gradient default is always painted; a solid or light / dark default becomes the editor's colour when the brush is chosen (unless the user locked theirs), resolved for the colour scheme. Canvas strokes and vector brushstrokes take it too, when they are given no colour. Canvas and vector have the same lock (`canvas.setColorLocked`, `vector.setColorLocked`), and a canvas colour taken from a light / dark default follows the scheme like the paint editor's; vector strokes already made keep theirs. |
|
|
25
26
|
|
|
@@ -142,10 +142,7 @@ Which facet sets which engine setting: [references/brush-facets.md](references/b
|
|
|
142
142
|
|
|
143
143
|
## Wet media
|
|
144
144
|
|
|
145
|
-
Watercolour, gouache and wet oil run on a fluid simulation: lay washes light to dark, let them
|
|
146
|
-
flow (`advance_wet_paint`), dry them (`dry_paint`) before glazing. Nothing moves for an agent
|
|
147
|
-
until you advance or dry it, and saving dries the paint. Load `pixerate-paint-watercolour`, and
|
|
148
|
-
read [references/wet-media.md](references/wet-media.md) for the engine and the wet tools.
|
|
145
|
+
Watercolour, gouache and wet oil run on a fluid simulation: lay washes light to dark, let them flow (`advance_wet_paint`), dry them (`dry_paint`) before glazing. Nothing moves for an agent until you advance or dry it, and saving dries the paint. Load `pixerate-paint-watercolour`, and read [references/wet-media.md](references/wet-media.md) for the engine and the wet tools. **Ghost paint and invisible ink** (`ghost` facet: `ghost-wash`, `ghost-gouache`, `ghost-oil`, `invisible-ink`) mix and flow while wet, then fade without leaving their own colour, leaving only a smear in the paint they touched: read [references/ghost.md](references/ghost.md).
|
|
149
146
|
|
|
150
147
|
## Oils and thick paint
|
|
151
148
|
|
|
@@ -295,7 +292,7 @@ Listing, saving, sharing and previewing brushes are the brush library's tools (`
|
|
|
295
292
|
| Tool | Use |
|
|
296
293
|
| --- | --- |
|
|
297
294
|
| `get_brush` | Read a brush as facets (`brush`), or the active brush as edited (no `id`), with the `engine` and `category` it paints with, `builtin` (an unchanged preset) and `strokePaint` (what its next stroke paints). Read before changing a brush you did not build. |
|
|
298
|
-
| `set_brush` | Choose the active brush (`id`, from `list_brush_presets`) and / or lay facets over it: `tip`, `marks`, `dynamics`, `behaviour`, `light`, `motion`, `colour` (objects merge, lists replace; marks of another kind replace the marks), `unset` facets to drop. Editor state, not saved: `create_brush` stores a brush. Returns `brush` (facets), `engine` and `problems` (values clamped). The old flat fields (`particle`, `impasto`, `behavior`…) are refused. |
|
|
295
|
+
| `set_brush` | Choose the active brush (`id`, from `list_brush_presets`) and / or lay facets over it: `tip`, `marks`, `dynamics`, `behaviour`, `light`, `ghost`, `motion`, `colour` (objects merge, lists replace; marks of another kind replace the marks), `unset` facets to drop. Editor state, not saved: `create_brush` stores a brush. Returns `brush` (facets), `engine` and `problems` (values clamped). The old flat fields (`particle`, `impasto`, `behavior`…) are refused. |
|
|
299
296
|
|
|
300
297
|
### Colour
|
|
301
298
|
|
|
@@ -345,7 +342,7 @@ Listing, saving, sharing and previewing brushes are the brush library's tools (`
|
|
|
345
342
|
|
|
346
343
|
| Tool | Use |
|
|
347
344
|
| --- | --- |
|
|
348
|
-
| `get_wet_paint` | Read the wet paint: `wet`, the clock, `paused`, `speed`, `tilt`, the kernel (`backend`, `message` when it runs slower than it could, e.g. on one thread because the page is not cross-origin isolated (COOP / COEP)), the GPU accelerator (`engine`) and each wet layer (`wetCells`, `wetBounds`, `activeTiles`, settings, flow map). Call after wet strokes. |
|
|
345
|
+
| `get_wet_paint` | Read the wet paint: `wet`, the clock, `paused`, `speed`, `tilt`, the kernel (`backend`, `message` when it runs slower than it could, e.g. on one thread because the page is not cross-origin isolated (COOP / COEP)), the GPU accelerator (`engine`) and each wet layer (`wetCells`, `wetBounds`, `activeTiles`, settings, flow map, and `ghost: { remaining }` while ghost paint is fading). Call after wet strokes. |
|
|
349
346
|
| `advance_wet_paint` | Let time pass: `steps` (120 = one second at the default speed) or `seconds`. The paint spreads, blooms, runs and dries. Not an undo step. Returns `steps`, `clock`, `stillWet`, `layers`. Call after a group of wet strokes, before `render_preview`. |
|
|
350
347
|
| `dry_paint` | Dry wet paint at once where it is (one layer with `layerId` or all, optionally inside `rect`). One undo step. Returns `dried` (layer ids and rectangles) and `stillWet`. Dry before glazing over a wash. |
|
|
351
348
|
| `wet_paper` | Pre-wet the paper with clear water over `rect` (default the canvas) on a layer, `amount` 0..1, for wet-in-wet. One undo step. Returns the rectangle and `wet`. Then paint into it. |
|
|
@@ -476,11 +473,7 @@ The host may add the shared document tools (see `pixerate-agent-tools`). A paint
|
|
|
476
473
|
- **Wet paint keeps changing.** A preview right after a wet stroke shows it before it has
|
|
477
474
|
flowed; `advance_wet_paint` first. Paint that should stay exactly where it was laid needs
|
|
478
475
|
`dry_paint` (or a dry medium).
|
|
479
|
-
- **Wet strokes on one layer interact**; washes that must not mix go on separate layers, or dry
|
|
480
|
-
the first before painting the second (glazing). At most 8 layers hold wet paint at once, and the simulation holds at most 328 wet tiles (256 × 256 px each) across them; water that spreads past
|
|
481
|
-
that limit is lost (`dry_paint` frees tiles). Multi-threaded wet media needs a cross-origin isolated
|
|
482
|
-
page (COOP / COEP, for `SharedArrayBuffer`) and runs on one thread otherwise, more slowly but with
|
|
483
|
-
the same result.
|
|
476
|
+
- **Wet strokes on one layer interact**; washes that must not mix go on separate layers, or dry the first before painting the second (glazing). Ghost paint (`ghost-wash`, `ghost-gouache`, `ghost-oil`, `invisible-ink`) only meets and smears paint on its own layer, so a ghost stroke on a new empty layer simply vanishes; ghost paint and light paint cannot share a layer while the ghost is fading. At most 8 layers hold wet paint at once, and the simulation holds at most 328 wet tiles (256 × 256 px each) across them; water that spreads past that limit is lost (`dry_paint` frees tiles). Multi-threaded wet media needs a cross-origin isolated page (COOP / COEP, for `SharedArrayBuffer`) and runs on one thread otherwise, more slowly but with the same result.
|
|
484
477
|
- **Undoing far back** past the wet undo memory (512 MB by default) leaves that paint dry as it
|
|
485
478
|
looked, rather than wet.
|
|
486
479
|
- **Replays repeat what was recorded**: strokes, fills, clears, flattened relief and wet events.
|
|
@@ -20,6 +20,7 @@ more; this is where each one went.
|
|
|
20
20
|
| Bristles | `tip.shape` `bristle` and `tip.bristle` |
|
|
21
21
|
| A brush's own gradient (paint) | `colour.default` (a gradient); `unset: ['colour']` drops it |
|
|
22
22
|
| Light | `light` (`amount`, `pressure`) |
|
|
23
|
+
| Ghost paint (linger, smear) | `ghost` (`linger`, `smear`); `unset: ['ghost']` drops it |
|
|
23
24
|
|
|
24
25
|
## Examples
|
|
25
26
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Ghost paint and invisible ink
|
|
2
|
+
|
|
3
|
+
Ghost paint is wet paint (`behaviour.surface: "wet"`) with a `ghost` facet (`linger` 0.5..60 s,
|
|
4
|
+
default 4; `smear` 0..1, default 0.3). While wet it looks and behaves like any watercolour,
|
|
5
|
+
gouache or wet oil: it flows with the water and its colour mixes visibly with the paint it meets.
|
|
6
|
+
Then its own colour fades away completely, leaving only what it did to the paint already on the
|
|
7
|
+
layer — a smear where it lifted and dragged that paint along. On bare paper it leaves nothing at
|
|
8
|
+
all.
|
|
9
|
+
|
|
10
|
+
## Presets and settings
|
|
11
|
+
|
|
12
|
+
- **`ghost-wash`**: transparent watercolour ghost (`linger: 4`, `smear: 0.35`).
|
|
13
|
+
- **`ghost-gouache`**: opaque gouache ghost that mixes strongly while wet, then vanishes (`linger: 4`, `smear: 0.45`).
|
|
14
|
+
- **`ghost-oil`**: slow wet oil ghost (`linger: 8`, `smear: 0.55`).
|
|
15
|
+
- **`invisible-ink`**: a ghost brush with `behaviour.wet.pigment: 0` and `smear: 0.6`. Nothing
|
|
16
|
+
shows on bare paper; it reveals itself only as a smear in the wet or dried paint it crosses.
|
|
17
|
+
Because it lays no pigment, it lays no tracer, needs no fade, and does not interrupt another
|
|
18
|
+
ghost already fading on the layer.
|
|
19
|
+
- Any wet paint brush becomes a ghost brush with `set_brush` `{ ghost: { linger, smear } }`;
|
|
20
|
+
`unset: ["ghost"]` makes it ordinary wet paint again.
|
|
21
|
+
|
|
22
|
+
## Working method
|
|
23
|
+
|
|
24
|
+
1. **Paint on the layer that holds the paint you want to disturb.** Wet paint is per layer:
|
|
25
|
+
a ghost stroke on a new empty layer has nothing to smear and vanishes into bare paper.
|
|
26
|
+
2. **Watch it mix while wet.** Call `advance_wet_paint` in short steps (`seconds: 0.5..1`) and
|
|
27
|
+
`render_preview` to see the ghost colour mixing and flowing with the layer's paint, and check
|
|
28
|
+
`get_wet_paint` (`layers[].ghost.remaining`, from 1 down to 0) to see how much of the fade is
|
|
29
|
+
left.
|
|
30
|
+
3. **Finish the fade.** Advance past `linger` seconds, or call `dry_paint` (which finishes the
|
|
31
|
+
ghost fade at once before baking). With `smear: 0`, ghost paint passes over dried paint and
|
|
32
|
+
leaves it untouched; with `smear > 0`, it lifts dried paint along its path (`rewet` scaled by
|
|
33
|
+
`smear`) and drags both wet and lifted paint along the stroke.
|
|
34
|
+
|
|
35
|
+
## Pitfalls
|
|
36
|
+
|
|
37
|
+
- **Wet paint is per layer.** Ghost paint only meets paint on its own layer. Painting a ghost
|
|
38
|
+
stroke on a new empty layer leaves nothing behind once it fades.
|
|
39
|
+
- **One ghost colour per layer at a time.** Painting a ghost stroke in a new colour on a layer
|
|
40
|
+
whose earlier ghost is still fading finishes the earlier ghost's colour fade at once (keeping
|
|
41
|
+
its smear) before starting the new colour.
|
|
42
|
+
- **Ghost and light paint cannot share a layer.** The ghost tracer uses the wet layer's light
|
|
43
|
+
channel, so a ghost stroke is refused on a layer that has light paint (`clear_light` or paint on
|
|
44
|
+
another layer), and a light brush is refused on a layer where ghost paint is still fading
|
|
45
|
+
(`dry_paint` first or use another layer). Once the ghost has faded, the layer is free again.
|
|
46
|
+
- **One solid colour per stroke.** Gradient paint, effect paint and multi-colour are refused on
|
|
47
|
+
ghost brushes.
|
|
@@ -77,6 +77,7 @@ block the light. See `references/light-paint.md` in `pixerate-paint-editor`.
|
|
|
77
77
|
| Cauliflower blooms | Add water into a drying wash; `bloom` up |
|
|
78
78
|
| A glowing (neon) wash | Dark paper (`set_paper` `color`), `glow-wash` or `light.amount` on a wet brush; flow, dry, `get_light` |
|
|
79
79
|
| Stained glass, a lightbox | `set_paper` `stained-glass` (or `backlight`); strong glazes for panes, opaque black lines above |
|
|
80
|
+
| Disturb or smear a wash without adding colour | `ghost-wash`, `ghost-gouache` or `invisible-ink` (`ghost` `linger`, `smear`) on the same layer; see `references/ghost.md` |
|
|
80
81
|
|
|
81
82
|
## Recipes
|
|
82
83
|
|