@pixerate/editor 0.250.0 → 0.252.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/agent/index.cjs +40 -41
- package/dist/agent/index.js +9 -10
- package/dist/animation/index.cjs +6 -7
- package/dist/animation/index.js +5 -6
- package/dist/animation-editor/index.cjs +70 -70
- package/dist/animation-editor/index.js +12 -12
- package/dist/brushes/index.cjs +2087 -0
- package/dist/brushes/index.d.cts +17 -0
- package/dist/brushes/index.d.ts +17 -0
- package/dist/brushes/index.js +2087 -0
- package/dist/brushes/library.d.cts +104 -0
- package/dist/brushes/library.d.ts +104 -0
- package/dist/brushes/migrate.d.cts +17 -0
- package/dist/brushes/migrate.d.ts +17 -0
- package/dist/brushes/normalize.d.cts +15 -0
- package/dist/brushes/normalize.d.ts +15 -0
- package/dist/brushes/presets.d.cts +12 -0
- package/dist/brushes/presets.d.ts +12 -0
- package/dist/brushes/profiles.d.cts +85 -0
- package/dist/brushes/profiles.d.ts +85 -0
- package/dist/brushes/resolve.d.cts +56 -0
- package/dist/brushes/resolve.d.ts +56 -0
- package/dist/brushes/schema.d.cts +29 -0
- package/dist/brushes/schema.d.ts +29 -0
- package/dist/brushes/tools.d.cts +37 -0
- package/dist/brushes/tools.d.ts +37 -0
- package/dist/brushes/types.d.cts +323 -0
- package/dist/brushes/types.d.ts +323 -0
- package/dist/{brushstrokeRender-2FHFLSEG.js → brushstrokeRender-5PYSKZIJ.js} +8 -8
- package/dist/{brushstrokeRender-QGRXOKDA.cjs → brushstrokeRender-7FLLSQEC.cjs} +14 -14
- package/dist/canvas/index.cjs +57 -58
- package/dist/canvas/index.js +31 -32
- package/dist/chart/index.cjs +159 -160
- package/dist/chart/index.js +9 -10
- package/dist/{chunk-NOHJP5TK.js → chunk-2ZJ4DT3M.js} +1 -1
- package/dist/{chunk-XZNU4DUX.cjs → chunk-3NS5C7FB.cjs} +76 -76
- package/dist/{chunk-UTI5IITZ.cjs → chunk-4ZC5QJE2.cjs} +3 -3
- package/dist/{chunk-SMSGP2HQ.js → chunk-5JNA6LLY.js} +1 -1
- package/dist/{chunk-RD7RX52G.cjs → chunk-5UEFBM2M.cjs} +207 -18
- package/dist/{chunk-WA44NKPF.js → chunk-62Z5WLRA.js} +1 -1
- package/dist/{chunk-BVRRIW7F.js → chunk-6GRUVGKU.js} +3 -3
- package/dist/{chunk-QARCM66V.js → chunk-6ZZKRH7R.js} +3 -3
- package/dist/{chunk-BP6KSGVD.js → chunk-7272D3K2.js} +4 -6
- package/dist/{chunk-NTRAVM2I.js → chunk-7P6VF3FG.js} +2 -2
- package/dist/chunk-APX63ILU.js +173 -0
- package/dist/{chunk-W7L4HUT2.cjs → chunk-CJ6TBL2N.cjs} +16 -16
- package/dist/{chunk-7PT4RJL5.cjs → chunk-EUIDTZNQ.cjs} +111 -113
- package/dist/{chunk-CXXXAZ7H.js → chunk-F6R67I3A.js} +1 -1
- package/dist/{chunk-I7NJPHWV.cjs → chunk-FQPUF2W2.cjs} +35 -606
- package/dist/{chunk-D5KGAO4Z.js → chunk-GCVFEPJG.js} +2 -573
- package/dist/{chunk-LEQKZGQI.js → chunk-GOBOCZZI.js} +1 -1
- package/dist/{chunk-KDLBJ6QR.js → chunk-GYMMNCFT.js} +3 -3
- package/dist/{chunk-NUTMINJZ.cjs → chunk-H7ET2ISK.cjs} +52 -52
- package/dist/chunk-HS6QDWDF.cjs +1029 -0
- package/dist/{chunk-T7KQEMAE.cjs → chunk-HUAISCUX.cjs} +18 -18
- package/dist/{chunk-YGQVCQTG.js → chunk-ILP77UD6.js} +1 -1
- package/dist/{chunk-S6OT6CTS.cjs → chunk-IWEVV63O.cjs} +31 -33
- package/dist/{chunk-M2VKFE5L.cjs → chunk-JFHBXNR2.cjs} +88 -88
- package/dist/{chunk-WPUXGDH4.cjs → chunk-JPEHXIB5.cjs} +10 -10
- package/dist/chunk-JSDND7DF.cjs +173 -0
- package/dist/{chunk-36ZTV7WO.js → chunk-L6Y7TSQ4.js} +1 -1
- package/dist/{chunk-YW43M56C.cjs → chunk-LFMKWGFL.cjs} +1 -1
- package/dist/{chunk-V6DT2CDH.js → chunk-M2TPMYJE.js} +1 -1
- package/dist/{chunk-LJZRHVZV.cjs → chunk-M5GLQQWG.cjs} +2 -2
- package/dist/{chunk-JEGJP4OW.js → chunk-MHLU6GRJ.js} +196 -7
- package/dist/{chunk-KMPM5JM5.js → chunk-MONXNVZK.js} +4 -6
- package/dist/chunk-MTKY6K3Q.js +1029 -0
- package/dist/{chunk-MOW3JMNG.cjs → chunk-N76AMOKE.cjs} +42 -42
- package/dist/{chunk-75K3W4D6.cjs → chunk-NKGB64CW.cjs} +16 -16
- package/dist/{chunk-SGPIVHJB.js → chunk-P3K2JCJA.js} +3 -3
- package/dist/chunk-PXDIAYB6.cjs +594 -0
- package/dist/{chunk-3TWOCSCY.js → chunk-QC3OXRE4.js} +9 -9
- package/dist/{chunk-YM6ZBTXG.cjs → chunk-QLSGTCYT.cjs} +23 -23
- package/dist/{chunk-7YW7T5TJ.js → chunk-RHPSE2YR.js} +2 -2
- package/dist/{chunk-44BMJJVA.cjs → chunk-RUONPPMC.cjs} +8 -8
- package/dist/{chunk-ATK6ABN3.cjs → chunk-SABJMH6M.cjs} +145 -12
- package/dist/{chunk-XWOLPNBW.cjs → chunk-SOSBOS5T.cjs} +22 -22
- package/dist/{chunk-PPFJHTW5.cjs → chunk-TFF2GTGN.cjs} +22 -24
- package/dist/{chunk-X7WRL5ZZ.cjs → chunk-TLOGFIIV.cjs} +37 -37
- package/dist/chunk-TXFWZ5ZJ.js +594 -0
- package/dist/{chunk-GXAK6Q5J.js → chunk-UFEDHACQ.js} +2 -2
- package/dist/{chunk-GA4EU4P3.cjs → chunk-UXETV2NC.cjs} +4 -4
- package/dist/{chunk-N4DFDI73.js → chunk-WKMUBATU.js} +1 -1
- package/dist/{chunk-3R5P3DVY.cjs → chunk-WRZ6C4TU.cjs} +6 -6
- package/dist/{chunk-U4NUOKBT.js → chunk-WZOGDKCQ.js} +134 -1
- package/dist/{chunk-6ADHGQ73.js → chunk-YBAPT7NL.js} +2 -4
- package/dist/color/index.cjs +4 -6
- package/dist/color/index.js +7 -9
- package/dist/export/index.cjs +7 -8
- package/dist/export/index.js +6 -7
- package/dist/extensions/index.cjs +10 -11
- package/dist/extensions/index.js +9 -10
- package/dist/gradient/index.cjs +33 -34
- package/dist/gradient/index.js +4 -5
- package/dist/image-editor/index.cjs +845 -844
- package/dist/image-editor/index.js +39 -38
- package/dist/index.cjs +16 -17
- package/dist/index.js +10 -11
- package/dist/paint/index.cjs +6 -4
- package/dist/paint/index.js +21 -19
- package/dist/paint-editor/brushes.d.cts +1 -2
- package/dist/paint-editor/brushes.d.ts +1 -2
- package/dist/paint-editor/index.cjs +2193 -694
- package/dist/paint-editor/index.js +1575 -76
- package/dist/paint-editor/mark-settings.d.cts +104 -0
- package/dist/paint-editor/mark-settings.d.ts +104 -0
- package/dist/paint-editor/procedural.d.cts +2 -75
- package/dist/paint-editor/procedural.d.ts +2 -75
- package/dist/paint-editor/stickers.d.cts +1 -22
- package/dist/paint-editor/stickers.d.ts +1 -22
- package/dist/raster/index.cjs +2 -2
- package/dist/raster/index.js +9 -9
- package/dist/stickers/index.cjs +10 -10
- package/dist/stickers/index.js +9 -9
- package/dist/tokens/index.cjs +3 -4
- package/dist/tokens/index.js +2 -3
- package/dist/tools/skill-evals.d.cts +8 -1
- package/dist/tools/skill-evals.d.ts +8 -1
- package/dist/typography/index.cjs +7 -8
- package/dist/typography/index.js +2 -3
- package/dist/vector/index.cjs +974 -974
- package/dist/vector/index.js +12 -12
- package/dist/video-editor/index.cjs +6 -7
- package/dist/video-editor/index.js +5 -6
- package/package.json +11 -1
- package/skills/README.md +2 -0
- package/skills/pixerate-brushes/SKILL.md +104 -0
- package/skills/pixerate-brushes-design/SKILL.md +88 -0
- package/skills/pixerate-brushes-design/evals/canvas-chalk.json +15 -0
- package/skills/pixerate-brushes-design/evals/pink-highlighter.json +15 -0
- package/skills/pixerate-brushes-design/evals/port-to-vector.json +17 -0
- package/dist/chunk-4JNWA3VT.cjs +0 -302
- package/dist/chunk-7AHBW2CQ.cjs +0 -200
- package/dist/chunk-F67XMVDI.js +0 -200
- package/dist/chunk-GT77U7QG.cjs +0 -2637
- package/dist/chunk-OTEPAQJX.js +0 -2637
- package/dist/chunk-WKH5ZAUA.js +0 -302
package/dist/vector/index.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
traceField,
|
|
27
27
|
traceVectorImage,
|
|
28
28
|
vectorTraceContours
|
|
29
|
-
} from "../chunk-
|
|
29
|
+
} from "../chunk-2ZJ4DT3M.js";
|
|
30
30
|
import {
|
|
31
31
|
applyHomography,
|
|
32
32
|
homographyFromPoints,
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
reverseMorphContour,
|
|
54
54
|
subpathToMorphContour,
|
|
55
55
|
turnMorphContour
|
|
56
|
-
} from "../chunk-
|
|
56
|
+
} from "../chunk-7P6VF3FG.js";
|
|
57
57
|
import {
|
|
58
58
|
DEFAULT_VECTOR_FONT,
|
|
59
59
|
IDENTITY_MATRIX,
|
|
@@ -526,9 +526,9 @@ import {
|
|
|
526
526
|
withVectorStrokes,
|
|
527
527
|
withVectorTargetPaint,
|
|
528
528
|
zigzagPaths
|
|
529
|
-
} from "../chunk-
|
|
530
|
-
import "../chunk-
|
|
531
|
-
import "../chunk-
|
|
529
|
+
} from "../chunk-GYMMNCFT.js";
|
|
530
|
+
import "../chunk-MTKY6K3Q.js";
|
|
531
|
+
import "../chunk-APX63ILU.js";
|
|
532
532
|
import {
|
|
533
533
|
createProvenance
|
|
534
534
|
} from "../chunk-M6DNZNVY.js";
|
|
@@ -566,16 +566,17 @@ import {
|
|
|
566
566
|
import "../chunk-V2ZCJRDM.js";
|
|
567
567
|
import {
|
|
568
568
|
GRAIN_PATTERNS
|
|
569
|
-
} from "../chunk-
|
|
569
|
+
} from "../chunk-TXFWZ5ZJ.js";
|
|
570
|
+
import "../chunk-GCVFEPJG.js";
|
|
570
571
|
import "../chunk-4D6KP5BV.js";
|
|
571
572
|
import "../chunk-ODBT55Q7.js";
|
|
572
|
-
import "../chunk-IRSTHLQQ.js";
|
|
573
573
|
import {
|
|
574
574
|
bytesToBase64,
|
|
575
575
|
decodePng,
|
|
576
576
|
isPng,
|
|
577
577
|
parseDataUrl
|
|
578
578
|
} from "../chunk-OTTT5N3K.js";
|
|
579
|
+
import "../chunk-IRSTHLQQ.js";
|
|
579
580
|
import "../chunk-HVVR5PZW.js";
|
|
580
581
|
import {
|
|
581
582
|
deflate
|
|
@@ -590,14 +591,13 @@ import {
|
|
|
590
591
|
HistoryManager
|
|
591
592
|
} from "../chunk-NS62CQ2B.js";
|
|
592
593
|
import "../chunk-5UJHB3BW.js";
|
|
593
|
-
import "../chunk-
|
|
594
|
+
import "../chunk-M2TPMYJE.js";
|
|
594
595
|
import {
|
|
595
596
|
hexToRgba
|
|
596
597
|
} from "../chunk-2WPNAGHI.js";
|
|
597
|
-
import "../chunk-
|
|
598
|
-
import "../chunk-
|
|
599
|
-
import "../chunk-
|
|
600
|
-
import "../chunk-F67XMVDI.js";
|
|
598
|
+
import "../chunk-7272D3K2.js";
|
|
599
|
+
import "../chunk-YBAPT7NL.js";
|
|
600
|
+
import "../chunk-MHLU6GRJ.js";
|
|
601
601
|
import "../chunk-6ONMQ6WF.js";
|
|
602
602
|
|
|
603
603
|
// src/vector/stylize.ts
|
|
@@ -182,17 +182,16 @@ require('../chunk-2BSBFBOA.cjs');
|
|
|
182
182
|
var _chunkWKPXOGZZcjs = require('../chunk-WKPXOGZZ.cjs');
|
|
183
183
|
|
|
184
184
|
|
|
185
|
-
var
|
|
185
|
+
var _chunkM5GLQQWGcjs = require('../chunk-M5GLQQWG.cjs');
|
|
186
186
|
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
var _chunkDWJJI6RTcjs = require('../chunk-DWJJI6RT.cjs');
|
|
190
|
-
require('../chunk-
|
|
190
|
+
require('../chunk-4ZC5QJE2.cjs');
|
|
191
191
|
require('../chunk-A6QWKBJP.cjs');
|
|
192
|
-
require('../chunk-
|
|
193
|
-
require('../chunk-
|
|
194
|
-
require('../chunk-
|
|
195
|
-
require('../chunk-7AHBW2CQ.cjs');
|
|
192
|
+
require('../chunk-EUIDTZNQ.cjs');
|
|
193
|
+
require('../chunk-TFF2GTGN.cjs');
|
|
194
|
+
require('../chunk-5UEFBM2M.cjs');
|
|
196
195
|
require('../chunk-IPJ3TEYR.cjs');
|
|
197
196
|
|
|
198
197
|
// src/video-editor/parse.ts
|
|
@@ -3675,7 +3674,7 @@ var VideoEditorController = (_class8 = class _VideoEditorController {
|
|
|
3675
3674
|
this.readOnly = _nullishCoalesce(options.readOnly, () => ( false));
|
|
3676
3675
|
this.previewScale = checkPreviewScale(_nullishCoalesce(options.previewScale, () => ( "auto")));
|
|
3677
3676
|
this.onChange = options.onChange;
|
|
3678
|
-
this.player = new (0,
|
|
3677
|
+
this.player = new (0, _chunkM5GLQQWGcjs.AnimationPlayer)({ clock: options.clock, duration: () => _chunkZBCT5MEAcjs.videoProjectDuration.call(void 0, this.project), loop: "none" });
|
|
3679
3678
|
this.state = this.computeState();
|
|
3680
3679
|
this.connect();
|
|
3681
3680
|
}
|
|
@@ -182,17 +182,16 @@ import {
|
|
|
182
182
|
} from "../chunk-NS62CQ2B.js";
|
|
183
183
|
import {
|
|
184
184
|
AnimationPlayer
|
|
185
|
-
} from "../chunk-
|
|
185
|
+
} from "../chunk-F6R67I3A.js";
|
|
186
186
|
import {
|
|
187
187
|
CUBIC_BEZIER_PRESETS,
|
|
188
188
|
evaluateEasing
|
|
189
189
|
} from "../chunk-5UJHB3BW.js";
|
|
190
|
-
import "../chunk-
|
|
190
|
+
import "../chunk-M2TPMYJE.js";
|
|
191
191
|
import "../chunk-2WPNAGHI.js";
|
|
192
|
-
import "../chunk-
|
|
193
|
-
import "../chunk-
|
|
194
|
-
import "../chunk-
|
|
195
|
-
import "../chunk-F67XMVDI.js";
|
|
192
|
+
import "../chunk-7272D3K2.js";
|
|
193
|
+
import "../chunk-YBAPT7NL.js";
|
|
194
|
+
import "../chunk-MHLU6GRJ.js";
|
|
196
195
|
import "../chunk-6ONMQ6WF.js";
|
|
197
196
|
|
|
198
197
|
// src/video-editor/parse.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixerate/editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.252.0",
|
|
4
4
|
"description": "UI-agnostic rich text and media editing core library",
|
|
5
5
|
"author": "Pixerate",
|
|
6
6
|
"license": "MIT",
|
|
@@ -194,6 +194,16 @@
|
|
|
194
194
|
"default": "./dist/paint-editor/index.cjs"
|
|
195
195
|
}
|
|
196
196
|
},
|
|
197
|
+
"./brushes": {
|
|
198
|
+
"import": {
|
|
199
|
+
"types": "./dist/brushes/index.d.ts",
|
|
200
|
+
"default": "./dist/brushes/index.js"
|
|
201
|
+
},
|
|
202
|
+
"require": {
|
|
203
|
+
"types": "./dist/brushes/index.d.cts",
|
|
204
|
+
"default": "./dist/brushes/index.cjs"
|
|
205
|
+
}
|
|
206
|
+
},
|
|
197
207
|
"./commands": {
|
|
198
208
|
"import": {
|
|
199
209
|
"types": "./dist/commands/index.d.ts",
|
package/skills/README.md
CHANGED
|
@@ -30,6 +30,7 @@ model and its general practice.
|
|
|
30
30
|
| [`pixerate-color`](pixerate-color/SKILL.md) | Colour inspection, WCAG accessibility and contrast optimization, CVD simulation, palette audits, harmonies, and OKLab/OKLCH blends. |
|
|
31
31
|
| [`pixerate-typography`](pixerate-typography/SKILL.md) | Fonts and fallback stacks, font loading, modular type scales and hierarchies, fluid sizes, readability and type-aware contrast audits, text segmentation, the font picker. |
|
|
32
32
|
| [`pixerate-stickers`](pixerate-stickers/SKILL.md) | Sticker libraries: finding stickers by ref (`provider:id`), categories, tags, tintable art and licences, for the editors that spray or place them. |
|
|
33
|
+
| [`pixerate-brushes`](pixerate-brushes/SKILL.md) | The shared brush library: brushes made of facets (medium, tip, marks, dynamics, behaviour, light, motion, colour), the presets, host profiles for paint, image, canvas and vector, and creating, checking and sharing brushes. |
|
|
33
34
|
|
|
34
35
|
## Workflow skills
|
|
35
36
|
|
|
@@ -51,6 +52,7 @@ request like "clean up this export" finds it.
|
|
|
51
52
|
| [`pixerate-paint-watercolour`](pixerate-paint-watercolour/SKILL.md) | Paint (`pixerate-paint-editor`) | Watercolour paper, light to dark with the paper's white kept, wet-in-wet and wet-on-dry washes, drying before glazing, steering the water. |
|
|
52
53
|
| [`pixerate-paint-oil-impasto`](pixerate-paint-oil-impasto/SKILL.md) | Paint (`pixerate-paint-editor`) | A toned ground, thin block-in to thick paint, pigment mixing, impasto relief and its light. |
|
|
53
54
|
| [`pixerate-paint-sketch-to-finish`](pixerate-paint-sketch-to-finish/SKILL.md) | Paint (`pixerate-paint-editor`) | Sketch, ink, flats under the lines, clipped shading and light, one named layer per pass. |
|
|
55
|
+
| [`pixerate-brushes-design`](pixerate-brushes-design/SKILL.md) | Brushes (`pixerate-brushes`) | From a description to a saved brush: the nearest preset, only the facets that change, checked for the host that will use it, previewed. |
|
|
54
56
|
| [`pixerate-video-social-cut`](pixerate-video-social-cut/SKILL.md) | Video (`pixerate-video-editor`) | Vertical or square reframes that fill the frame, the hook first, platform lengths, titles in the safe area. |
|
|
55
57
|
| [`pixerate-video-colour-grade`](pixerate-video-colour-grade/SKILL.md) | Video (`pixerate-video-editor`) | Correct and match shots, then one look on an adjustment clip; LUTs at moderate strength with skin protected. |
|
|
56
58
|
| [`pixerate-video-montage`](pixerate-video-montage/SKILL.md) | Video (`pixerate-video-editor`) | Selects on the beat, varied pacing, short transitions with handles, music under everything and a clean ending. |
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
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.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Brushes
|
|
7
|
+
|
|
8
|
+
A brush is made of **facets** that say what it is and how it behaves, not which engine draws it.
|
|
9
|
+
Only `id`, `name`, `kind` and `tip.shape` are required; every other field takes the default of
|
|
10
|
+
the engine the facets pick, so a brush stores only what makes it what it is. The library holds the
|
|
11
|
+
built-in presets (read-only) and the user's brushes, shared by every editor that paints.
|
|
12
|
+
|
|
13
|
+
| Facet (field) | What it holds |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| Kind | `mark` lays a material; `tool` works on paint already down. |
|
|
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
|
+
| 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` lays stickers), size in px, hardness, spacing, opacity, flow, blend mode. |
|
|
19
|
+
| Marks | `continuous` dabs (default), `particles` (strands, springs, ribbons, sparks) or `objects` (each mark an editable sticker). |
|
|
20
|
+
| Dynamics | Pen feel: pressure to size and opacity, smoothing, tilt, velocity, jitter, rotation. |
|
|
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
|
+
| Light | Light the brush gives off (`amount`), plus suggested layer `spill` and `glow`. |
|
|
23
|
+
| Motion | Animation after painting (live effect paint, particle `waveSpeed`). |
|
|
24
|
+
| Colour | A `default` colour, a `palette` of up to 16, `own` (always its own colour). A gradient default is always painted; a solid one is a suggestion. |
|
|
25
|
+
|
|
26
|
+
How media map to facets: a **pencil** or **charcoal** is `dry` with high `grain` and tilt;
|
|
27
|
+
**ink** is a hard round tip with pressure to size (a pen thins with velocity); **watercolour**
|
|
28
|
+
and **wet oil** are `paint` on `surface: 'wet'`; **impasto** is `surface: 'thick'`; an
|
|
29
|
+
**airbrush** is `spray`, soft and low flow; a **highlighter** is `ink` / `highlighter`, a
|
|
30
|
+
multiply chisel tip with a little light and `spill` radius 0; **particle** and **sticker**
|
|
31
|
+
brushes are `marks` particles or objects on a `stamp` tip.
|
|
32
|
+
|
|
33
|
+
## Host profiles
|
|
34
|
+
|
|
35
|
+
Each host renders a part of this. `check_brush` says what a host refuses (errors) and what it
|
|
36
|
+
paints without (warnings), each with a fix; lists and writes use the current host.
|
|
37
|
+
|
|
38
|
+
| Host | Renders |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| Paint editor (`paint`) | Everything. |
|
|
41
|
+
| 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. |
|
|
42
|
+
| Canvas (`canvas`) | Dry dab brushes along a path (no tools, wet, thick, particles, objects or light); velocity is ignored. |
|
|
43
|
+
| Vector strokes (`vector`) | As canvas, but light brushes paint as plain colour. |
|
|
44
|
+
|
|
45
|
+
## Working method
|
|
46
|
+
|
|
47
|
+
1. **Find the nearest brush.** `list_brush_presets` with `medium`, `variety`, `kind` or `text`.
|
|
48
|
+
It lists only what this host can render (`all: true` lists the rest with `renderable`).
|
|
49
|
+
2. **Read it.** `describe_brush` for the full spec, the engine it resolves to and its check.
|
|
50
|
+
3. **Make a brush.** `create_brush` with a new `id`, a `name`, `basedOn` the nearest preset and
|
|
51
|
+
only the facets that change (objects merge; lists replace). Read `problems` (values clamped or
|
|
52
|
+
dropped) and `warnings`. A brush the host can't render is refused and nothing is saved.
|
|
53
|
+
4. **Look at it.** `preview_brush` when the host has a renderer; otherwise paint a test stroke
|
|
54
|
+
in the editor (`set_brush` with the new id, then `paint_stroke`).
|
|
55
|
+
5. **Tune it.** `update_brush` with the facets to change, or `unset` to drop whole facets. It
|
|
56
|
+
returns the leaf paths `changed`. Built-in presets can't be changed: `duplicate_brush` first.
|
|
57
|
+
6. **Share it.** `export_brushes` writes a library file; `import_brushes` adds one (version 1
|
|
58
|
+
files of the paint editor's older brushes are migrated). `check_brush` with `host` before
|
|
59
|
+
handing a brush to another editor.
|
|
60
|
+
|
|
61
|
+
## Best practices
|
|
62
|
+
|
|
63
|
+
- Start from the nearest preset and change two or three facets; a brush from nothing gets
|
|
64
|
+
engine defaults that rarely suit a medium.
|
|
65
|
+
- Test on the paper and colour the brush will be used on: grain response and glazes look
|
|
66
|
+
different on smooth and rough paper.
|
|
67
|
+
- Give light brushes dark paper, and give highlighters a `light.spill` radius of 0 so the
|
|
68
|
+
glow stays on the stroke.
|
|
69
|
+
- Keep `variety` truthful (it is how people find the brush) and add `tags` for the job
|
|
70
|
+
(`lettering`, `foliage`).
|
|
71
|
+
- Use `colour.palette` for suggested colours and `colour.own` only for brushes that must
|
|
72
|
+
always paint their own (a rainbow marker).
|
|
73
|
+
|
|
74
|
+
## Pitfalls
|
|
75
|
+
|
|
76
|
+
- **A facet the host refuses.** `create_brush` and `update_brush` refuse it with the facet and
|
|
77
|
+
fix; `check_brush` returns `degraded`, the brush with those facets stripped, to start from.
|
|
78
|
+
- **Ids.** Built-in ids can't be reused or changed; a taken id is refused (update it instead).
|
|
79
|
+
- **Stamps.** Particle marks lay only the editor's stamps (`editor:star`…); sticker (`objects`)
|
|
80
|
+
marks take any sticker ref from `find_stickers`.
|
|
81
|
+
- **Out-of-range values** are refused by the schema (`tip.size` is 1..2500 px); a stored brush
|
|
82
|
+
is clamped on import and reported in `problems`.
|
|
83
|
+
- **The paint editor's own brush tools** (`set_brush`, `save_brush`, its `export_brushes`)
|
|
84
|
+
still work on its brushes; this library's tools are namespaced apart.
|
|
85
|
+
|
|
86
|
+
## Workflow skills
|
|
87
|
+
|
|
88
|
+
- `pixerate-brushes-design`: from a description ("a soft pink highlighter", "chalk for the
|
|
89
|
+
canvas") to a saved, checked brush.
|
|
90
|
+
|
|
91
|
+
## Tool reference
|
|
92
|
+
|
|
93
|
+
| Tool | Use |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| `list_brush_presets` | Find brushes this host renders: `kind`, `medium`, `variety`, `tool`, `tag`, `text`, `source` (all, builtin, user), `all`, `offset`, `limit`. Returns `brushes` (id, name, builtin, kind, medium, variety or tool, category, engine, tip, size, marks, surface, light) and `total`. Call first. |
|
|
96
|
+
| `describe_brush` | One brush by `id`: its full facet `brush`, `builtin`, `engine`, `category` and `check` for this host. Unknown ids are refused with the closest ones. |
|
|
97
|
+
| `create_brush` | Save a new brush: `id`, `name`, optional `basedOn`, and the facets. Normalised and checked for this host; refused brushes save nothing. Returns `id`, `brush`, `engine`, `problems`, `warnings`. |
|
|
98
|
+
| `update_brush` | Change a saved brush: facets to merge in, `unset` facets to drop. Refuses built-ins (duplicate first) and changes the host can't render. Returns `brush`, `changed` paths, `problems`, `warnings`. |
|
|
99
|
+
| `duplicate_brush` | Copy any brush, built-ins included, to a saved brush (`newId` default `<id>-copy`, `name`). Returns the new `id` and `brush`; then `update_brush` it. |
|
|
100
|
+
| `remove_brush` | Delete a saved brush for good (export it first to keep a copy). Built-ins are refused. Returns `removed`. |
|
|
101
|
+
| `check_brush` | Check a brush (`id`, or an unsaved `brush` spec) for a `host` (paint, image, canvas, vector). Returns `ok`, `issues` (facet, severity, reason, fix) and, when refused, `degraded`. |
|
|
102
|
+
| `export_brushes` | Library file (pixerate-brushes v2) of the saved brushes or the `ids` given. Returns `file`, for `import_brushes`. |
|
|
103
|
+
| `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`. |
|
|
104
|
+
| `preview_brush` | Only when the host renders previews: a sample stroke with a brush (`id`, `width`, `height`, `color`) as an image. |
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixerate-brushes-design
|
|
3
|
+
description: The brush design workflow in the Pixerate brush library - turning a description ("a soft pink highlighter", "chalk for canvas strokes", "make this brush work in the vector editor") into a saved brush, by picking the nearest preset, changing only the facets that matter, checking it against the host that will use it and previewing it. Use when asked to make, design, customise, adapt or port a brush, or when create_brush, check_brush or list_brush_presets are available. Load with pixerate-brushes, which lists every tool.
|
|
4
|
+
metadata:
|
|
5
|
+
kind: workflow
|
|
6
|
+
reference: pixerate-brushes
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Designing a brush
|
|
10
|
+
|
|
11
|
+
A brush is a preset with a few facets changed. The presets already hold good settings for each
|
|
12
|
+
medium (pencil grain, ink velocity, watercolour water), so the fastest good brush starts from
|
|
13
|
+
the nearest one and changes two or three facets: the colour, the tip, how it feels. What a brush
|
|
14
|
+
may use depends on the editor that will paint with it: check it against that host before saving.
|
|
15
|
+
|
|
16
|
+
This skill is the method. `pixerate-brushes` has the full tool reference.
|
|
17
|
+
|
|
18
|
+
## Goal and quality bar
|
|
19
|
+
|
|
20
|
+
- The brush is saved under a clear `id` and `name`, with a truthful `medium` and `variety`.
|
|
21
|
+
- `check_brush` for the host it is for returns `ok: true`; any warnings are understood.
|
|
22
|
+
- It differs from its base preset only where the request asks (`describe_brush` shows it).
|
|
23
|
+
- Built-in presets are untouched.
|
|
24
|
+
|
|
25
|
+
## Inputs to confirm
|
|
26
|
+
|
|
27
|
+
Ask when you cannot tell from the request; say what you assumed when you can.
|
|
28
|
+
|
|
29
|
+
- **Host:** which editor will use it (paint by default; canvas and vector strokes take only dry
|
|
30
|
+
dab brushes, the image editor no wet, thick or particle brushes).
|
|
31
|
+
- **Medium and character:** what it imitates (pencil, ink, chalk, watercolour, marker…), and
|
|
32
|
+
the size, softness and texture.
|
|
33
|
+
- **Colour:** a default colour or palette, or the user's own colour (the default).
|
|
34
|
+
|
|
35
|
+
## Working method
|
|
36
|
+
|
|
37
|
+
1. **Find the base.** `list_brush_presets` with `medium` or `variety`, or `text`. Pick the
|
|
38
|
+
closest; `describe_brush` it to read its facets.
|
|
39
|
+
**Check:** the base's `check` is `ok` for the target host (or `check_brush` with `host`).
|
|
40
|
+
2. **Create from it.** `create_brush` with a new `id`, `name`, `basedOn` and only the facets
|
|
41
|
+
that change: `variety` for what it is now, `colour.default` / `colour.palette`, `tip`
|
|
42
|
+
(size, hardness, roundness, angle), `dynamics`, `behaviour.grain`.
|
|
43
|
+
**Check:** `problems` is empty or understood; nothing refused.
|
|
44
|
+
3. **Check it for the host.** `check_brush` with `id` and `host`. A refusal names the facet and
|
|
45
|
+
fix; its `degraded` brush is a good next spec.
|
|
46
|
+
**Check:** `ok: true`.
|
|
47
|
+
4. **Look at it.** `preview_brush` when available; then `update_brush` to tune (each call
|
|
48
|
+
returns the paths `changed`).
|
|
49
|
+
**Check:** `describe_brush` shows the intended facets.
|
|
50
|
+
|
|
51
|
+
## Decision table
|
|
52
|
+
|
|
53
|
+
| Situation | Approach |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| A colour variant of a preset | `basedOn` it, set `colour.default` (and a `palette`), keep everything else. |
|
|
56
|
+
| For canvas or vector strokes | Base on a dry preset (pencil, pastel, charcoal, marker, ink); no wet surface, particles, stickers or tools; no light on canvas. |
|
|
57
|
+
| A brush that must work in another editor | `check_brush` with that `host`, then `create_brush` from its `degraded` brush under a new id. |
|
|
58
|
+
| A texture (chalk, charcoal, dry brush) | Raise `behaviour.grain` (0.8..1) and add `dynamics.sizeJitter`; test on rough paper. |
|
|
59
|
+
| A light brush (neon, glow) | `light.amount`, and paint it on dark paper; a highlighter keeps `light.spill.radius` 0. |
|
|
60
|
+
| A change to a built-in | `duplicate_brush`, then `update_brush` the copy. |
|
|
61
|
+
|
|
62
|
+
## Recipes
|
|
63
|
+
|
|
64
|
+
**A pink highlighter.** `create_brush` `{ id: "pink-highlighter", name: "Pink highlighter",
|
|
65
|
+
basedOn: "highlighter", colour: { default: "#ff6ec7" } }`, then `check_brush`.
|
|
66
|
+
|
|
67
|
+
**Chalk for canvas strokes.** On the canvas host, `create_brush` `{ id: "chalk", name: "Chalk",
|
|
68
|
+
basedOn: "soft-pastel", variety: "chalk", behaviour: { grain: 1 }, dynamics: { sizeJitter: 0.12 } }`.
|
|
69
|
+
|
|
70
|
+
**Port a wet brush to vector.** `check_brush` `{ id, host: "vector" }`; `create_brush` from the
|
|
71
|
+
`degraded` brush with `id` `<id>-vector`; `check_brush` again.
|
|
72
|
+
|
|
73
|
+
## Pitfalls
|
|
74
|
+
|
|
75
|
+
- **Starting from nothing.** A brush without `basedOn` gets engine defaults (a hard round dab);
|
|
76
|
+
it rarely looks like the medium asked for.
|
|
77
|
+
- **A host that refuses the base.** A wet or particle preset can't be the base of a canvas
|
|
78
|
+
brush; set `behaviour.surface` to `dry` or start from a dry preset.
|
|
79
|
+
- **Lists replace.** Giving `colour.palette` or `tip.stamps` replaces the whole list; include
|
|
80
|
+
every entry you want.
|
|
81
|
+
- **Changing a built-in.** `update_brush` refuses built-ins; duplicate first.
|
|
82
|
+
|
|
83
|
+
## Tools used
|
|
84
|
+
|
|
85
|
+
- `list_brush_presets`, `describe_brush`: find the base preset and read its facets.
|
|
86
|
+
- `create_brush`, `update_brush`, `duplicate_brush`: make and tune the brush.
|
|
87
|
+
- `check_brush`: prove it works for the host, and get a degraded spec when it doesn't.
|
|
88
|
+
- `preview_brush`: look at a sample stroke when the host renders previews.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "I'm drawing brushed strokes on the canvas. Make a soft, grainy chalk brush with the id chalk that the canvas can actually use.",
|
|
3
|
+
"fixture": { "editor": "brushes", "host": "canvas" },
|
|
4
|
+
"checks": [
|
|
5
|
+
{ "why": "the canvas can render it", "tool": "check_brush", "args": { "id": "chalk", "host": "canvas" }, "expect": { "ok": true } },
|
|
6
|
+
{ "why": "a dry chalk", "tool": "describe_brush", "args": { "id": "chalk" }, "expect": { "brush": { "kind": "mark", "medium": "dry", "variety": "chalk" } } },
|
|
7
|
+
{ "why": "it catches the paper grain strongly", "tool": "describe_brush", "args": { "id": "chalk" }, "expect": { "brush": { "behaviour": { "grain": { "$min": 0.8 } } } } },
|
|
8
|
+
{ "why": "soft-edged", "tool": "describe_brush", "args": { "id": "chalk" }, "expect": { "brush": { "tip": { "hardness": { "$max": 0.6 } } } } }
|
|
9
|
+
],
|
|
10
|
+
"solution": [
|
|
11
|
+
{ "tool": "list_brush_presets", "args": { "medium": "dry" } },
|
|
12
|
+
{ "tool": "create_brush", "args": { "id": "chalk", "name": "Chalk", "basedOn": "soft-pastel", "variety": "chalk", "behaviour": { "grain": 1 }, "dynamics": { "sizeJitter": 0.12 } } },
|
|
13
|
+
{ "tool": "check_brush", "args": { "id": "chalk", "host": "canvas" } }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "Make me a pink highlighter brush, saved as pink-highlighter, that behaves like the built-in highlighter but starts out pink.",
|
|
3
|
+
"fixture": { "editor": "brushes" },
|
|
4
|
+
"checks": [
|
|
5
|
+
{ "why": "a saved brush, not a built-in", "tool": "describe_brush", "args": { "id": "pink-highlighter" }, "expect": { "builtin": false, "check": { "ok": true } } },
|
|
6
|
+
{ "why": "still a highlighter: multiply chisel ink with no spill", "tool": "describe_brush", "args": { "id": "pink-highlighter" }, "expect": { "brush": { "medium": "ink", "variety": "highlighter", "tip": { "shape": "chisel", "blend": "multiply" }, "light": { "spill": { "radius": 0 } } } } },
|
|
7
|
+
{ "why": "it starts out pink", "tool": "describe_brush", "args": { "id": "pink-highlighter" }, "expect": { "brush": { "colour": { "default": { "$expr": "(([r, g, b]) => r > 200 && b > 120 && g < r - 60)([1, 3, 5].map((i) => parseInt(v.slice(i, i + 2), 16)))" } } } } },
|
|
8
|
+
{ "why": "the built-in highlighter is untouched", "tool": "describe_brush", "args": { "id": "highlighter" }, "expect": { "brush": { "colour": { "default": "#fff200" } } } }
|
|
9
|
+
],
|
|
10
|
+
"solution": [
|
|
11
|
+
{ "tool": "list_brush_presets", "args": { "variety": "highlighter" } },
|
|
12
|
+
{ "tool": "create_brush", "args": { "id": "pink-highlighter", "name": "Pink highlighter", "basedOn": "highlighter", "colour": { "default": "#ff6ec7" } } },
|
|
13
|
+
{ "tool": "check_brush", "args": { "id": "pink-highlighter" } }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "A teammate's brush team-wash is in the library, but it won't work for vector brushstrokes. Make a copy called team-wash-vector that does, and leave theirs as it is.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "brushes",
|
|
5
|
+
"setup": [{ "tool": "create_brush", "args": { "id": "team-wash", "name": "Team wash", "basedOn": "watercolor-wash", "tags": ["team"] } }]
|
|
6
|
+
},
|
|
7
|
+
"checks": [
|
|
8
|
+
{ "why": "the copy works in the vector editor", "tool": "check_brush", "args": { "id": "team-wash-vector", "host": "vector" }, "expect": { "ok": true } },
|
|
9
|
+
{ "why": "the copy keeps the wash's tip", "tool": "describe_brush", "args": { "id": "team-wash-vector" }, "expect": { "brush": { "tip": { "size": 90, "roundness": 0.45 } } } },
|
|
10
|
+
{ "why": "the teammate's brush still paints wet", "tool": "describe_brush", "args": { "id": "team-wash" }, "expect": { "brush": { "behaviour": { "surface": "wet" } } } }
|
|
11
|
+
],
|
|
12
|
+
"solution": [
|
|
13
|
+
{ "tool": "check_brush", "args": { "id": "team-wash", "host": "vector" } },
|
|
14
|
+
{ "tool": "create_brush", "args": { "id": "team-wash-vector", "name": "Team wash (vector)", "basedOn": "team-wash", "behaviour": { "surface": "dry" } } },
|
|
15
|
+
{ "tool": "check_brush", "args": { "id": "team-wash-vector", "host": "vector" } }
|
|
16
|
+
]
|
|
17
|
+
}
|