@pixerate/editor 0.251.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.
@@ -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
+ }