@pixerate/editor 0.267.0 → 0.268.1

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.
Files changed (83) hide show
  1. package/dist/animation-editor/index.cjs +62 -62
  2. package/dist/animation-editor/index.js +6 -6
  3. package/dist/brushes/index.cjs +198 -72
  4. package/dist/brushes/index.d.cts +4 -3
  5. package/dist/brushes/index.d.ts +4 -3
  6. package/dist/brushes/index.js +136 -10
  7. package/dist/brushes/library.d.cts +27 -1
  8. package/dist/brushes/library.d.ts +27 -1
  9. package/dist/brushes/profiles.d.cts +4 -0
  10. package/dist/brushes/profiles.d.ts +4 -0
  11. package/dist/brushes/schema.d.cts +4 -0
  12. package/dist/brushes/schema.d.ts +4 -0
  13. package/dist/brushes/sources.d.cts +114 -0
  14. package/dist/brushes/sources.d.ts +114 -0
  15. package/dist/brushes/types.d.cts +37 -5
  16. package/dist/brushes/types.d.ts +37 -5
  17. package/dist/brushes/ui.d.cts +40 -4
  18. package/dist/brushes/ui.d.ts +40 -4
  19. package/dist/{brushstrokeRender-NLFPEBGI.js → brushstrokeRender-A727TTNQ.js} +6 -6
  20. package/dist/{brushstrokeRender-L7JYRR2R.cjs → brushstrokeRender-WR2N5HHY.cjs} +22 -22
  21. package/dist/canvas/index.cjs +13 -13
  22. package/dist/canvas/index.js +1 -1
  23. package/dist/{chunk-J2TNIZ55.cjs → chunk-2WOGXEDX.cjs} +1 -1
  24. package/dist/{chunk-JGWVZPT6.js → chunk-3XDSNIGF.js} +72 -5
  25. package/dist/{chunk-EXB2EGBE.cjs → chunk-62MFUHSI.cjs} +16 -16
  26. package/dist/{chunk-GCVFEPJG.js → chunk-ACTHSQOI.js} +182 -0
  27. package/dist/{chunk-EF7LZAXQ.js → chunk-BAZMCFVL.js} +1 -1
  28. package/dist/{chunk-HIO6E7LC.cjs → chunk-BPJSI4NT.cjs} +2 -2
  29. package/dist/{chunk-XVOP3CGQ.cjs → chunk-EU2ZZA6L.cjs} +393 -62
  30. package/dist/{chunk-YIC6MAJ2.js → chunk-HFY5LG5J.js} +1 -1
  31. package/dist/{chunk-7UKFXXWL.js → chunk-HVO6XCI4.js} +1 -1
  32. package/dist/{chunk-LHPEG5AU.cjs → chunk-J4GXP53R.cjs} +140 -91
  33. package/dist/{chunk-OKHKA43L.cjs → chunk-JBB3GDBB.cjs} +330 -216
  34. package/dist/{chunk-AGNUD5BI.js → chunk-KZI3YWKW.js} +351 -20
  35. package/dist/{chunk-FGJHJIMN.js → chunk-LDOD7VCT.js} +59 -10
  36. package/dist/{chunk-EYSHTYLG.js → chunk-LETF75CA.js} +1 -1
  37. package/dist/{chunk-FQPUF2W2.cjs → chunk-NIBFKXMD.cjs} +217 -35
  38. package/dist/{chunk-G7NHE2VD.cjs → chunk-NPWWSCWT.cjs} +35 -35
  39. package/dist/{chunk-OSEXT7JL.js → chunk-QNY7BDFP.js} +1 -1
  40. package/dist/{chunk-PXDIAYB6.cjs → chunk-STLTOISW.cjs} +34 -214
  41. package/dist/{chunk-4IDUYB45.js → chunk-UVTO3D4E.js} +130 -16
  42. package/dist/{chunk-TXFWZ5ZJ.js → chunk-W6JDUXP3.js} +4 -184
  43. package/dist/{chunk-LA5Y4ETA.cjs → chunk-YOVXQHA3.cjs} +23 -23
  44. package/dist/{chunk-DT4YQUGT.cjs → chunk-YXP6X3SY.cjs} +101 -34
  45. package/dist/image-editor/adjustment-layers.d.cts +8 -0
  46. package/dist/image-editor/adjustment-layers.d.ts +8 -0
  47. package/dist/image-editor/index.cjs +857 -853
  48. package/dist/image-editor/index.js +30 -26
  49. package/dist/paint/index.cjs +5 -5
  50. package/dist/paint/index.js +11 -11
  51. package/dist/paint-editor/brush-library-tools.d.cts +12 -2
  52. package/dist/paint-editor/brush-library-tools.d.ts +12 -2
  53. package/dist/paint-editor/brush-model.d.cts +29 -1
  54. package/dist/paint-editor/brush-model.d.ts +29 -1
  55. package/dist/paint-editor/brush-source-art.d.cts +32 -0
  56. package/dist/paint-editor/brush-source-art.d.ts +32 -0
  57. package/dist/paint-editor/controller.d.cts +6 -1
  58. package/dist/paint-editor/controller.d.ts +6 -1
  59. package/dist/paint-editor/dab-stroke.d.cts +2 -0
  60. package/dist/paint-editor/dab-stroke.d.ts +2 -0
  61. package/dist/paint-editor/engine.d.cts +11 -2
  62. package/dist/paint-editor/engine.d.ts +11 -2
  63. package/dist/paint-editor/index.cjs +576 -481
  64. package/dist/paint-editor/index.d.cts +3 -1
  65. package/dist/paint-editor/index.d.ts +3 -1
  66. package/dist/paint-editor/index.js +127 -32
  67. package/dist/paint-editor/stamp-tip.d.cts +8 -5
  68. package/dist/paint-editor/stamp-tip.d.ts +8 -5
  69. package/dist/paint-editor/thumbnails.d.cts +6 -0
  70. package/dist/paint-editor/thumbnails.d.ts +6 -0
  71. package/dist/paint-editor/tip-grain.d.cts +34 -0
  72. package/dist/paint-editor/tip-grain.d.ts +34 -0
  73. package/dist/raster/index.cjs +2 -2
  74. package/dist/raster/index.js +9 -9
  75. package/dist/vector/index.cjs +1002 -1002
  76. package/dist/vector/index.js +7 -7
  77. package/package.json +110 -1
  78. package/skills/pixerate-brushes/SKILL.md +35 -8
  79. package/skills/pixerate-brushes-design/SKILL.md +8 -1
  80. package/skills/pixerate-image-editor/SKILL.md +1 -1
  81. package/skills/pixerate-paint-editor/SKILL.md +6 -0
  82. package/skills/pixerate-paint-editor/references/brush-facets.md +3 -1
  83. package/skills/pixerate-paint-sketch-to-finish/SKILL.md +1 -0
@@ -35,7 +35,7 @@ import {
35
35
  traceField,
36
36
  traceVectorImage,
37
37
  vectorTraceContours
38
- } from "../chunk-YIC6MAJ2.js";
38
+ } from "../chunk-HFY5LG5J.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-OSEXT7JL.js";
69
+ } from "../chunk-QNY7BDFP.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-4IDUYB45.js";
559
+ } from "../chunk-UVTO3D4E.js";
560
560
  import {
561
561
  snapshotBrushLibrary
562
- } from "../chunk-AGNUD5BI.js";
562
+ } from "../chunk-KZI3YWKW.js";
563
563
  import "../chunk-JL6YH5WD.js";
564
564
  import {
565
565
  createProvenance
@@ -598,19 +598,19 @@ import {
598
598
  } from "../chunk-MV7CYFMJ.js";
599
599
  import "../chunk-V2ZCJRDM.js";
600
600
  import "../chunk-GSTSZPSR.js";
601
+ import "../chunk-W6JDUXP3.js";
601
602
  import {
602
603
  GRAIN_PATTERNS
603
- } from "../chunk-TXFWZ5ZJ.js";
604
- import "../chunk-GCVFEPJG.js";
604
+ } from "../chunk-ACTHSQOI.js";
605
605
  import "../chunk-4D6KP5BV.js";
606
606
  import "../chunk-ODBT55Q7.js";
607
+ import "../chunk-IRSTHLQQ.js";
607
608
  import {
608
609
  bytesToBase64,
609
610
  decodePng,
610
611
  isPng,
611
612
  parseDataUrl
612
613
  } from "../chunk-OTTT5N3K.js";
613
- import "../chunk-IRSTHLQQ.js";
614
614
  import "../chunk-HVVR5PZW.js";
615
615
  import {
616
616
  deflate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.267.0",
3
+ "version": "0.268.1",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -375,6 +375,115 @@
375
375
  }
376
376
  }
377
377
  },
378
+ "typesVersions": {
379
+ "*": {
380
+ "grammar": [
381
+ "./dist/grammar/index.d.ts"
382
+ ],
383
+ "extensions": [
384
+ "./dist/extensions/index.d.ts"
385
+ ],
386
+ "serializers": [
387
+ "./dist/serializers/index.d.ts"
388
+ ],
389
+ "spreadsheet": [
390
+ "./dist/spreadsheet/index.d.ts"
391
+ ],
392
+ "history": [
393
+ "./dist/history/index.d.ts"
394
+ ],
395
+ "animation": [
396
+ "./dist/animation/index.d.ts"
397
+ ],
398
+ "animation-editor": [
399
+ "./dist/animation-editor/index.d.ts"
400
+ ],
401
+ "video-editor": [
402
+ "./dist/video-editor/index.d.ts"
403
+ ],
404
+ "canvas": [
405
+ "./dist/canvas/index.d.ts"
406
+ ],
407
+ "agent": [
408
+ "./dist/agent/index.d.ts"
409
+ ],
410
+ "tools": [
411
+ "./dist/tools/index.d.ts"
412
+ ],
413
+ "raster": [
414
+ "./dist/raster/index.d.ts"
415
+ ],
416
+ "cms": [
417
+ "./dist/cms/index.d.ts"
418
+ ],
419
+ "paint": [
420
+ "./dist/paint/index.d.ts"
421
+ ],
422
+ "image-editor": [
423
+ "./dist/image-editor/index.d.ts"
424
+ ],
425
+ "image-editor/selection-worker": [
426
+ "./dist/image-editor/selection-worker.d.ts"
427
+ ],
428
+ "paint-editor": [
429
+ "./dist/paint-editor/index.d.ts"
430
+ ],
431
+ "brushes": [
432
+ "./dist/brushes/index.d.ts"
433
+ ],
434
+ "commands": [
435
+ "./dist/commands/index.d.ts"
436
+ ],
437
+ "persistence": [
438
+ "./dist/persistence/index.d.ts"
439
+ ],
440
+ "generation": [
441
+ "./dist/generation/index.d.ts"
442
+ ],
443
+ "compare": [
444
+ "./dist/compare/index.d.ts"
445
+ ],
446
+ "tokens": [
447
+ "./dist/tokens/index.d.ts"
448
+ ],
449
+ "color": [
450
+ "./dist/color/index.d.ts"
451
+ ],
452
+ "typography": [
453
+ "./dist/typography/index.d.ts"
454
+ ],
455
+ "gradient": [
456
+ "./dist/gradient/index.d.ts"
457
+ ],
458
+ "export": [
459
+ "./dist/export/index.d.ts"
460
+ ],
461
+ "parameters": [
462
+ "./dist/parameters/index.d.ts"
463
+ ],
464
+ "vector": [
465
+ "./dist/vector/index.d.ts"
466
+ ],
467
+ "chart": [
468
+ "./dist/chart/index.d.ts"
469
+ ],
470
+ "chart-maps": [
471
+ "./dist/chart-maps/index.d.ts"
472
+ ],
473
+ "effects": [
474
+ "./dist/effects/index.d.ts"
475
+ ],
476
+ "stickers": [
477
+ "./dist/stickers/index.d.ts"
478
+ ],
479
+ "diagram": [
480
+ "./dist/diagram/index.d.ts"
481
+ ],
482
+ "bridge": [
483
+ "./dist/bridge/index.d.ts"
484
+ ]
485
+ }
486
+ },
378
487
  "bin": {
379
488
  "pixerate-mcp-bridge": "./dist/bridge/cli.js"
380
489
  },
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: pixerate-brushes
3
- description: How to find, describe, create, change, check and share brushes in the Pixerate brush library through list_brush_presets, describe_brush, create_brush, update_brush, duplicate_brush, remove_brush, check_brush, export_brushes, import_brushes and preview_brush - brushes made of facets (kind, medium and variety or tool, tip, marks, dynamics, behaviour, light, motion, colour), the built-in presets, and the host profiles that say what the paint editor, image editor, canvas and vector strokes can render. Use when asked to make, design, tweak, save, copy, delete, export, import or check a brush, find a brush for a medium (pencil, ink, watercolour, oil, airbrush, highlighter), or make a brush work in another editor.
3
+ description: How to find, describe, create, change, check and share brushes in the Pixerate brush library through list_brush_presets, describe_brush, create_brush, update_brush, duplicate_brush, remove_brush, check_brush, export_brushes, import_brushes, preview_brush, add_brush_source and list_brush_sources - brushes made of facets (kind, medium and variety or tool, tip, marks, dynamics, behaviour, light, motion, colour), image tips and tip grain made from image sources, the built-in presets, and the host profiles that say what the paint editor, image editor, canvas and vector strokes can render. Use when asked to make, design, tweak, save, copy, delete, export, import or check a brush, make a brush from an image (a scanned mark, a leaf, a texture), give a brush grain, find a brush for a medium (pencil, ink, watercolour, oil, airbrush, highlighter), or make a brush work in another editor.
4
4
  ---
5
5
 
6
6
  # Brushes
@@ -15,9 +15,9 @@ built-in presets (read-only) and the user's brushes, shared by every editor that
15
15
  | Kind | `mark` lays a material; `tool` works on paint already down. |
16
16
  | Medium and variety | Marks: what it lays (`paint`, `ink`, `dry`, `spray`) and what kind (`oil`, `watercolor`, `gouache`, `pencil`, `charcoal`, `airbrush`, `marker`, `highlighter`…). Descriptive, for finding brushes; a wet brush whose variety is `watercolor`, `gouache` or `oil` paints that medium. |
17
17
  | Tool | Tools: `eraser`, `blender`, `smudge`, and on wet paint `water`, `dryer`, `blow`, `blot`, `wet-blend`, `wet-drag`. |
18
- | Tip | `shape` (`round`, `flat`, `chisel` are ellipses set by `roundness` and `angle`; `bristle` has a tuft; `stamp` takes the shape of `stamps`: an editor stamp `editor:star` or any sticker ref from `find_stickers`), size in px, hardness, spacing, opacity, flow, blend mode. |
18
+ | Tip | `shape` (`round`, `flat`, `chisel` are ellipses set by `roundness` and `angle`; `bristle` has a tuft; `stamp` takes the shape of `stamps`: an editor stamp `editor:star`, any sticker ref from `find_stickers`, or an image source `source:<id>` from `list_brush_sources`), size in px, hardness (an image tip fades towards its edges below 1), spacing, opacity, flow, blend mode, and `grain`: texture inside each dab (`source`: a pattern such as `rough`, `canvas`, `sanded`, or `source:<id>`; `mode` `texturised` stays put on the canvas, `moving` rolls with the tip; `scale`, `depth`, `contrast`, `invert`). |
19
19
  | Marks | `continuous` dabs (default; on a stamp tip every dab is the first stamp's shape, in the paint colour), `scatter` (a spray: droplets across the tip, `density`, `size`), `particles` (strands, springs, ribbons, sparks; textured dots from the stamps) or `objects` (each mark an editable sticker, in its own colours). |
20
- | Dynamics | Pen feel: pressure to size and opacity, smoothing, tilt, velocity, jitter, rotation. |
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
23
  | Motion | Animation after painting (live effect paint, particle `waveSpeed`). |
@@ -31,7 +31,16 @@ and **wet oil** are `paint` on `surface: 'wet'`; **impasto** is `surface: 'thick
31
31
  pressure to size); **crayon** and **chalk** are `dry` with high `grain`; a **highlighter** is
32
32
  `ink` / `highlighter`, a multiply chisel tip with a little light, `spill` radius 0, fluorescent
33
33
  yellow by default; a **stamp brush** is a `stamp` tip with continuous marks; **particle** and
34
- **sticker** brushes are `marks` particles or objects on a `stamp` tip.
34
+ **sticker** brushes are `marks` particles or objects on a `stamp` tip. An **image brush** (a
35
+ scanned charcoal mark, a leaf, a dry-brush texture) is a `stamp` tip whose stamp is an image
36
+ source, usually with `tip.grain`, `angleJitter`, `flip` and a little `scatter` so repeats don't
37
+ show.
38
+
39
+ **Image sources** are the images tips and grain are made from, kept in the library with their
40
+ bytes (a grey mask, at most 512 px) and their licence. `add_brush_source` makes one from a PNG:
41
+ the marks are read from its transparency, its dark parts (a scan on paper) or its light parts
42
+ (white on black). Library files (`export_brushes`) and saved paintings carry the sources their
43
+ brushes name, so they paint and replay the same anywhere.
35
44
 
36
45
  ## Host profiles
37
46
 
@@ -40,9 +49,9 @@ paints without (warnings), each with a fix; lists and writes use the current hos
40
49
 
41
50
  | Host | Renders |
42
51
  | --- | --- |
43
- | Paint editor (`paint`) | Everything. |
44
- | Image editor (`image`) | Dry dabs on round, flat and chisel tips, the Mixer Brush and the eraser; no wet or thick surface, particles, objects, light or motion. Pick one with `set_brush_preset`. |
45
- | Canvas (`canvas`) | Dry dab brushes along a path (no tools, wet, thick, particles, objects or light); velocity is ignored. Draw with one as `canvas.drawFreehand` `brush`. |
52
+ | Paint editor (`paint`) | Everything, image tips and tip grain included. |
53
+ | Image editor (`image`) | Dry dabs on round, flat and chisel tips, the Mixer Brush and the eraser; no wet or thick surface, particles, objects, stamp or image tips, light or motion; it paints without tip grain and `count`. Pick one with `set_brush_preset`. |
54
+ | Canvas (`canvas`) | Dry dab brushes along a path (no tools, wet, thick, particles, objects, stamp or image tips, or light); velocity, tip grain and `count` are ignored. Draw with one as `canvas.drawFreehand` `brush`. |
46
55
  | Vector strokes (`vector`) | As canvas, plus wet paint (watercolour, gouache, wet oils: simulated in the stroke's own area, then dried), the Mixer Brush, and the smudge and blender tools (acting on the shapes beneath the stroke); light brushes paint as plain colour. The wet tools (water, hair dryer, blow, wet blend, wet drag, blot), thick paint, particles, objects and erasers are refused. Draw with one as `vector.addBrushstroke` `brushId`. |
47
56
 
48
57
  Every host lists the presets its profile admits and the library's saved brushes it admits, and
@@ -66,7 +75,11 @@ drawn.
66
75
  in the editor (`set_brush` with the new id, then `paint_stroke`).
67
76
  5. **Tune it.** `update_brush` with the facets to change, or `unset` to drop whole facets. It
68
77
  returns the leaf paths `changed`. Built-in presets can't be changed: `duplicate_brush` first.
69
- 6. **Share it.** `export_brushes` writes a library file; `import_brushes` adds one (version 1
78
+ 6. **From an image.** `add_brush_source` with the PNG (`channel` when `auto` picks the wrong
79
+ part; keep the `licence` it came with), then `create_brush` with `tip: { shape: "stamp",
80
+ stamps: ["source:<id>"] }` for an image tip, or `tip.grain.source` for grain.
81
+ `list_brush_sources` lists them and which brushes use each.
82
+ 7. **Share it.** `export_brushes` writes a library file; `import_brushes` adds one (version 1
70
83
  files of the paint editor's older brushes are migrated). `check_brush` with `host` before
71
84
  handing a brush to another editor.
72
85
 
@@ -92,6 +105,13 @@ drawn.
92
105
  to make its preview visible: choosing the brush makes that default the user's colour.
93
106
  - Stamp tips paint the sticker's shape in the paint colour; to keep a sticker's own colours, use
94
107
  `marks` objects instead.
108
+ - Image tips: crop the image to the mark and give it a transparent or plain background, so the
109
+ dab is the mark and not its box. Spacing 0.2–0.4 for a continuous mark, above 1 for separate
110
+ prints; add `angleJitter`, `flip` and `scatter` so the same image doesn't repeat visibly.
111
+ - Grain: `texturised` grain (default) is a texture the stroke reveals, like paper; `moving` grain
112
+ belongs to the tip and rolls with it (a sponge, a roller). Depth 0.4–0.7 reads as texture;
113
+ 1 leaves only the peaks. Use `tip.grain` for the tool's texture and `behaviour.grain` for the
114
+ paper's.
95
115
 
96
116
  ## Pitfalls
97
117
 
@@ -107,6 +127,11 @@ drawn.
107
127
  (`editor:star`…). A ref the host's sticker library can't load is refused with the closest
108
128
  refs. Only the paint editor renders stamp tips and scatter marks; canvas, vector and the image
109
129
  editor refuse them (`check_brush` says so).
130
+ - **Image sources.** A `source:<id>` the library doesn't have is refused, with the closest ids;
131
+ add it first. Replacing a source's image (`overwrite`) changes every brush that names it, but
132
+ not strokes already painted. Objects marks take stickers only, so an image source there is
133
+ dropped (`problems` says so). Brush packs are often licensed for personal use only: keep the
134
+ `licence` text with the source.
110
135
  - **Out-of-range values** are refused by the schema (`tip.size` is 1..2500 px); a stored brush
111
136
  is clamped on import and reported in `problems`.
112
137
  - **The paint editor paints from this library.** Its `set_brush` picks a brush by id here and
@@ -133,3 +158,5 @@ drawn.
133
158
  | `export_brushes` | Library file (pixerate-brushes v2) of the saved brushes or the `ids` given. Returns `file`, for `import_brushes`. |
134
159
  | `import_brushes` | Add a library `file` (v2, v1 migrated, or a bare list): built-in ids and taken ids are skipped unless `overwrite`. Returns `added`, `replaced`, `skipped`, `problems`. |
135
160
  | `preview_brush` | Only when the host renders previews: a sample stroke with a brush (`id`, `width`, `height`, `color`) as an image. |
161
+ | `add_brush_source` | Add an image (`name`, `image` PNG data: URL, optional `id`, `channel` auto / alpha / darkness / lightness, `invert`, `licence`, `origin`, `overwrite`) as a source for image tips and grain. Returns `id`, `ref` (`source:<id>`), `width`, `height`, `problems`, `replaced`. Then `create_brush` / `update_brush` with the ref in `tip.stamps` or `tip.grain.source`. |
162
+ | `list_brush_sources` | The library's image sources (`text`, `offset`, `limit`). Returns `sources` (id, ref, name, width, height, licence, origin, `usedBy` brush ids) and `total`. Call before naming a `source:` ref. |
@@ -57,7 +57,8 @@ Ask when you cannot tell from the request; say what you assumed when you can.
57
57
  | For canvas strokes | Base on a dry preset (pencil, pastel, charcoal, marker, ink); no wet surface, particles, stickers or tools; no light. |
58
58
  | For vector strokes | As canvas, but a wet surface (watercolour, gouache, wet oil), the Mixer Brush and the smudge and blender tools work too; no thick paint, particles, stickers, erasers or wet tools. |
59
59
  | A brush that must work in another editor | `check_brush` with that `host`, then `create_brush` from its `degraded` brush under a new id. |
60
- | A texture (chalk, charcoal, dry brush) | Raise `behaviour.grain` (0.8..1) and add `dynamics.sizeJitter`; test on rough paper. |
60
+ | A texture (chalk, charcoal, dry brush) | Raise `behaviour.grain` (0.8..1) and add `dynamics.sizeJitter`; test on rough paper. For texture that shows on any paper, give the tip its own grain: `tip.grain` `{ source: "sanded", depth: 0.6 }` (paint editor; other hosts paint without it). |
61
+ | A brush from an image (a scanned mark, a leaf, a texture) | `list_brush_sources`, or `add_brush_source` with the PNG (keep its `licence`); then `tip` `{ shape: "stamp", stamps: ["source:<id>"] }`, spacing 0.2–0.4, `dynamics.angleJitter`, `flip` and a little `scatter`. The image as grain instead: `tip.grain.source`. Paint editor only. |
61
62
  | A light brush (neon, glow) | `light.amount`, and paint it on dark paper; a highlighter keeps `light.spill.radius` 0. |
62
63
  | A colour that depends on the background (chalk, white ink) | `colour.default` as a light / dark pair `{ light, dark }`: the editor takes the side for its colour scheme when the brush is chosen. |
63
64
  | A shape as the tip (stars, leaves, a logo) | `tip.shape` stamp with `stamps` (an editor stamp or a ref from `find_stickers`), continuous marks; it paints in the user's colour. Keep the sticker's colours with `marks` objects. Paint editor only. |
@@ -74,6 +75,11 @@ basedOn: "highlighter", colour: { default: "#ff6ec7" } }`, then `check_brush`.
74
75
  `{ id: "board-chalk", name: "Board chalk", basedOn: "chalk", colour: { default: { light:
75
76
  "#334155", dark: "#f8fafc" } } }`: white chalk in dark mode, slate on light paper.
76
77
 
78
+ **A charcoal brush from a scan.** `add_brush_source` `{ name: "Charcoal scan", image: <PNG>,
79
+ channel: "darkness" }` → `create_brush` `{ id: "scan-charcoal", name: "Scan charcoal", basedOn:
80
+ "charcoal-stick", tip: { shape: "stamp", stamps: ["source:charcoal-scan"], spacing: 0.25, grain:
81
+ { source: "rough", depth: 0.5 } }, dynamics: { angleJitter: 0.3, flip: "xy" } }` → `preview_brush`.
82
+
77
83
  **Port a wet brush to vector.** `check_brush` `{ id, host: "vector" }`; `create_brush` from the
78
84
  `degraded` brush with `id` `<id>-vector`; `check_brush` again.
79
85
 
@@ -94,3 +100,4 @@ basedOn: "highlighter", colour: { default: "#ff6ec7" } }`, then `check_brush`.
94
100
  - `create_brush`, `update_brush`, `duplicate_brush`: make and tune the brush.
95
101
  - `check_brush`: prove it works for the host, and get a degraded spec when it doesn't.
96
102
  - `preview_brush`: look at a sample stroke when the host renders previews.
103
+ - `add_brush_source`, `list_brush_sources`: images for image tips and grain.
@@ -195,7 +195,7 @@ in the source frame at the document's bit depth, colour mode and profile. Read
195
195
  | Tool | Use it to |
196
196
  | --- | --- |
197
197
  | `set_adjustments` | Set base controls and existing layer parameters in one undo step: `values` is a map of control id or `layers.<layerId>.<controlId>` path to number; `label` is echoed. Values are clamped to range; returns `applied` and `clamped` (and a note when `tint` is set on a process 1 edit). Unknown ids fail and change nothing. Cannot set curves points, booleans or colours. |
198
- | `add_adjustment_layer` | Add a layer above the other adjustment layers and below annotations (or directly above `aboveId`, or at the top of group `parentId`): `kind` (curves, levels, hueSaturation, vibrance, colorBalance, blackWhite, photoFilter, invert, posterize, threshold), optional `params` merged with neutral defaults, `opacity` 0..1 (default 1), `blend` (default normal), `name`. With a selection the layer is masked by it (`useSelection`, default true; `false` for a global layer; `masked` in the result). `clipped: true` (with `aboveId`) clips it to the layer below in the same undo step so it adjusts only that layer; refused when nothing is below. Returns the layer (with its new id), its stack index, `masked` and `clipped`. The only tool that sets curves points, `colorize`, `preserveLuminosity`, a black and white `tint` or a photo filter `color`. |
198
+ | `add_adjustment_layer` | Add a layer above the other adjustment layers and below annotations (or directly above `aboveId`, or at the top of group `parentId`): `kind` (curves, levels, hueSaturation, vibrance, colorBalance, blackWhite, photoFilter, invert, posterize, threshold), optional `params` merged with neutral defaults and nested, not dotted (`{ master: { gamma: 1.2 } }`, never `{ "master.gamma": 1.2 }`; an unknown or mistyped key is refused and the error lists the accepted shape), `opacity` 0..1 (default 1), `blend` (default normal), `name`. With a selection the layer is masked by it (`useSelection`, default true; `false` for a global layer; `masked` in the result). `clipped: true` (with `aboveId`) clips it to the layer below in the same undo step so it adjusts only that layer; refused when nothing is below. Returns the layer (with its new id), its stack index, `masked` and `clipped`. The only tool that sets curves points, `colorize`, `preserveLuminosity`, a black and white `tint` or a photo filter `color`. |
199
199
  | `select_all` | Select › All. Returns the selection summary (`empty`, `bounds`, `area`, `percent`). |
200
200
  | `deselect` | Clear the selection so edits apply to the whole layer. Returns the empty summary. |
201
201
  | `invert_selection` | Select › Inverse (soft edges stay soft; with nothing selected, selects all). Returns the summary. |
@@ -42,6 +42,12 @@ is never part of a layer. Coordinates are document pixels, (0, 0) top-left, y do
42
42
  same two ratios. `get_mixer_brush` reads what the brush carries; `clean_mixer_brush` wipes it.
43
43
  - **Grain**: a brush's grain response times the paper's `depth` decides how much light pressure
44
44
  skips the valleys. Pencil, pastel and charcoal are grainy; airbrush, marker and ink are not.
45
+ A brush can also carry its own texture, `tip.grain` (a pattern such as `sanded` or `canvas`, or
46
+ an image source; `texturised` stays put, `moving` rolls with the tip), which shows on any paper.
47
+ - **Image tips**: a stamp tip whose stamp is an image source (`source:<id>`, added with the
48
+ brush library's `add_brush_source`) paints every dab as that image in the paint colour, with
49
+ hardness, roundness, angle, pressure size, `dynamics.count`, `flip` and jitter. Strokes record
50
+ the source, and the saved painting carries its bytes, so replays and exports match.
45
51
  - **Strokes are data.** Every stroke is recorded (brush, colour, raw points, seed, symmetry
46
52
  copies) and gets a `strokeId`. `replay_strokes` paints recorded strokes again, exactly or
47
53
  varied. That is the main way an agent should make many similar marks.
@@ -8,7 +8,9 @@ more; this is where each one went.
8
8
  | Engine setting | Facet |
9
9
  | --- | --- |
10
10
  | Tip size, hardness, spacing, angle, roundness, opacity, flow, blend | `tip` |
11
- | Smoothing, pressure, tilt, velocity, jitter, scatter, rotation | `dynamics` |
11
+ | Smoothing, pressure, tilt, velocity, jitter, scatter, rotation, dabs per step (`count`), random `flip` | `dynamics` |
12
+ | Image tip | `tip` `{ shape: 'stamp', stamps: ['source:<id>'] }` (an image source from `add_brush_source`) |
13
+ | Texture inside the tip | `tip.grain` `{ source: 'sanded' or 'source:<id>', mode: 'texturised' or 'moving', scale, depth, contrast, invert }` |
12
14
  | Grain, pick-up and mix (behavior), blender and smudge strength | `behaviour` (`grain`, `exchange`, `strength`, `distance`, `length`, `mixing`) |
13
15
  | Mixer Brush reservoir | `behaviour.exchange.reservoir` (`load`, `refill`, `loadsColour`) |
14
16
  | Wet engine (medium, water, pigment, body…) | `behaviour.surface` `wet` and `behaviour.wet` |
@@ -66,6 +66,7 @@ This skill is the method. `pixerate-paint-editor` has the full tool reference.
66
66
  | Clean geometric lines (curves, circles, borders) | `stroke_path` with SVG path data and a `pressure` taper, on the Ink layer |
67
67
  | Flats | `marker` or a flat brush on a layer under the ink |
68
68
  | Patterned or textured flats (sky, gradient, galaxy) | `set_effect_paint` with a provider generator, then a flat dry brush on the Flats layer; `set_color` after |
69
+ | Textured passes (dry brush, sponge, foliage) | A brush with `tip.grain` (`set_brush` `{ tip: { grain: { source: "sanded", depth: 0.6 } } }`) or an image tip from the brush library, with `dynamics.angleJitter` and `flip` so repeats don't show |
69
70
  | Shadows | Clipped layer, `multiply` or `shadow`, a cool colour |
70
71
  | Light, glow | Clipped layer, `highlight` or `screen` |
71
72
  | Warm or cool a whole area | Clipped layer in `tint` |