@pixerate/editor 0.266.2 → 0.267.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 +2 -2
- package/dist/agent/index.js +1 -1
- package/dist/animation-editor/controller.d.cts +8 -0
- package/dist/animation-editor/controller.d.ts +8 -0
- package/dist/animation-editor/effect-tools.d.cts +1 -1
- package/dist/animation-editor/effect-tools.d.ts +1 -1
- package/dist/animation-editor/index.cjs +172 -105
- package/dist/animation-editor/index.js +91 -24
- package/dist/brushes/index.cjs +59 -59
- package/dist/brushes/index.js +5 -5
- package/dist/brushes/profiles.d.cts +6 -1
- package/dist/brushes/profiles.d.ts +6 -1
- package/dist/{brushstrokeRender-FSUWXUZY.cjs → brushstrokeRender-L7JYRR2R.cjs} +16 -16
- package/dist/{brushstrokeRender-KD453OBX.js → brushstrokeRender-NLFPEBGI.js} +4 -4
- package/dist/canvas/brushTypes.d.cts +12 -0
- package/dist/canvas/brushTypes.d.ts +12 -0
- package/dist/canvas/brushstroke.d.cts +1 -1
- package/dist/canvas/brushstroke.d.ts +1 -1
- package/dist/canvas/drawController.d.cts +19 -4
- package/dist/canvas/drawController.d.ts +19 -4
- package/dist/canvas/index.cjs +144 -105
- package/dist/canvas/index.js +46 -7
- package/dist/{chunk-XORJ7UZO.cjs → chunk-3VHH6V67.cjs} +13 -12
- package/dist/{chunk-T2LDTEXK.js → chunk-4IDUYB45.js} +2217 -56
- package/dist/chunk-7UKFXXWL.js +802 -0
- package/dist/chunk-ADMRNWR7.js +340 -0
- package/dist/{chunk-CIJBSUM5.js → chunk-AGNUD5BI.js} +2 -2
- package/dist/{chunk-WLUVZKVD.cjs → chunk-DT4YQUGT.cjs} +32 -32
- package/dist/{chunk-DXYHQ2VN.js → chunk-EF7LZAXQ.js} +1 -1
- package/dist/chunk-EXB2EGBE.cjs +802 -0
- package/dist/{chunk-4ODRXQRW.js → chunk-EYSHTYLG.js} +1 -1
- package/dist/{chunk-R44Y3EFS.js → chunk-FGJHJIMN.js} +8 -336
- package/dist/{chunk-AQZQWXEU.cjs → chunk-G7NHE2VD.cjs} +35 -35
- package/dist/{chunk-XC6DPRYI.js → chunk-GSTSZPSR.js} +154 -949
- package/dist/{chunk-VRK322ZC.cjs → chunk-HIO6E7LC.cjs} +2 -2
- package/dist/{chunk-TOID45I2.cjs → chunk-J2TNIZ55.cjs} +1 -1
- package/dist/{chunk-YHDHFJUC.cjs → chunk-J5VQYK7T.cjs} +217 -1012
- package/dist/{chunk-3C33YTNN.js → chunk-JGWVZPT6.js} +2 -2
- package/dist/{chunk-ACFSFUQH.js → chunk-JL6YH5WD.js} +4 -0
- package/dist/{chunk-3SBLVGOM.cjs → chunk-LA5Y4ETA.cjs} +23 -23
- package/dist/{chunk-MVUQSK5J.cjs → chunk-LHPEG5AU.cjs} +107 -435
- package/dist/{chunk-DOZ6F2K2.js → chunk-NSETJI74.js} +3 -2
- package/dist/{chunk-XRXFVRGY.cjs → chunk-OKHKA43L.cjs} +2364 -203
- package/dist/{chunk-LK4SXL3V.js → chunk-OSEXT7JL.js} +1 -1
- package/dist/{chunk-PE6YJMQT.cjs → chunk-PFHJS4HE.cjs} +20 -19
- package/dist/{chunk-7KNW3WXZ.cjs → chunk-QEVLRLUN.cjs} +63 -0
- package/dist/{chunk-OTN6VB5S.cjs → chunk-RDFHWAHL.cjs} +5 -1
- package/dist/{chunk-6JL2D5SG.js → chunk-VE6UKYQ2.js} +3 -2
- package/dist/{chunk-RFJZGTHA.cjs → chunk-XVOP3CGQ.cjs} +9 -9
- package/dist/{chunk-EZOJBP4D.js → chunk-YIC6MAJ2.js} +1 -1
- package/dist/chunk-YZWM6ZIP.cjs +340 -0
- package/dist/{chunk-472INMWH.js → chunk-ZA7L5YJB.js} +63 -0
- package/dist/commands/builtins.d.cts +12 -1
- package/dist/commands/builtins.d.ts +12 -1
- package/dist/commands/index.cjs +2 -2
- package/dist/commands/index.js +1 -1
- package/dist/image-editor/controller.d.cts +1 -1
- package/dist/image-editor/controller.d.ts +1 -1
- package/dist/image-editor/index.cjs +837 -833
- package/dist/image-editor/index.js +105 -101
- package/dist/paint/index.cjs +5 -3
- package/dist/paint/index.js +46 -44
- package/dist/paint-editor/controller.d.cts +5 -3
- package/dist/paint-editor/controller.d.ts +5 -3
- package/dist/paint-editor/index.cjs +832 -2295
- package/dist/paint-editor/index.js +285 -1748
- package/dist/paint-editor/path-samples.d.cts +2 -0
- package/dist/paint-editor/path-samples.d.ts +2 -0
- package/dist/paint-editor/presence.d.cts +20 -1
- package/dist/paint-editor/presence.d.ts +20 -1
- package/dist/stickers/helpers.d.cts +2 -0
- package/dist/stickers/helpers.d.ts +2 -0
- package/dist/stickers/index.cjs +41 -35
- package/dist/stickers/index.js +22 -16
- package/dist/stickers/types.d.cts +4 -2
- package/dist/stickers/types.d.ts +4 -2
- package/dist/vector/backdrop.d.cts +13 -0
- package/dist/vector/backdrop.d.ts +13 -0
- package/dist/vector/brushstroke.d.cts +54 -7
- package/dist/vector/brushstroke.d.ts +54 -7
- package/dist/vector/brushstrokeMedia.d.cts +96 -0
- package/dist/vector/brushstrokeMedia.d.ts +96 -0
- package/dist/vector/controller.d.cts +17 -3
- package/dist/vector/controller.d.ts +17 -3
- package/dist/vector/index.cjs +1846 -1386
- package/dist/vector/index.d.cts +2 -0
- package/dist/vector/index.d.ts +2 -0
- package/dist/vector/index.js +517 -57
- package/dist/vector/render.d.cts +6 -0
- package/dist/vector/render.d.ts +6 -0
- package/dist/vector/types.d.cts +14 -0
- package/dist/vector/types.d.ts +14 -0
- package/package.json +1 -1
- package/skills/pixerate-animation-editor/SKILL.md +1 -0
- package/skills/pixerate-brushes/SKILL.md +2 -2
- package/skills/pixerate-brushes-design/SKILL.md +7 -4
- package/skills/pixerate-brushes-design/evals/port-to-vector.json +8 -8
- package/skills/pixerate-canvas/SKILL.md +11 -1
- package/skills/pixerate-image-editor/SKILL.md +19 -64
- package/skills/pixerate-image-editor/references/color-management.md +2 -1
- package/skills/pixerate-image-editor/references/free-transform.md +12 -0
- package/skills/pixerate-image-editor/references/layer-effects.md +10 -0
- package/skills/pixerate-image-editor/references/painting.md +17 -0
- package/skills/pixerate-image-editor/references/photoshop-files.md +1 -1
- package/skills/pixerate-image-editor/references/shapes-and-type.md +14 -0
- package/skills/pixerate-image-editor/references/smart-objects.md +10 -0
- package/skills/pixerate-paint-editor/SKILL.md +8 -4
- package/skills/pixerate-paint-editor/references/wet-media.md +9 -0
- package/skills/pixerate-vector/SKILL.md +16 -6
- package/skills/pixerate-vector/references/best-practices.md +1 -0
- package/skills/pixerate-vector/references/commands.md +19 -0
package/dist/vector/render.d.cts
CHANGED
|
@@ -571,6 +571,12 @@ export interface VectorSceneRenderOptions {
|
|
|
571
571
|
};
|
|
572
572
|
/** With `viewportSize`: groups, text and instances smaller than this many screen pixels draw as one rectangle in their main colour (default 2; 0 turns it off). */
|
|
573
573
|
lod?: number;
|
|
574
|
+
/**
|
|
575
|
+
* `live` (default): wet brushstrokes show the paint as laid until they settle (re-render when
|
|
576
|
+
* `onVectorBrushstrokesSettled` fires; the controller notifies then). `settled`: settle them
|
|
577
|
+
* first, as exports must.
|
|
578
|
+
*/
|
|
579
|
+
brushstrokes?: 'live' | 'settled';
|
|
574
580
|
}
|
|
575
581
|
/**
|
|
576
582
|
* The document layer. Render the nodes inside `<g transform={transform}>` and `defs` in a
|
package/dist/vector/render.d.ts
CHANGED
|
@@ -571,6 +571,12 @@ export interface VectorSceneRenderOptions {
|
|
|
571
571
|
};
|
|
572
572
|
/** With `viewportSize`: groups, text and instances smaller than this many screen pixels draw as one rectangle in their main colour (default 2; 0 turns it off). */
|
|
573
573
|
lod?: number;
|
|
574
|
+
/**
|
|
575
|
+
* `live` (default): wet brushstrokes show the paint as laid until they settle (re-render when
|
|
576
|
+
* `onVectorBrushstrokesSettled` fires; the controller notifies then). `settled`: settle them
|
|
577
|
+
* first, as exports must.
|
|
578
|
+
*/
|
|
579
|
+
brushstrokes?: 'live' | 'settled';
|
|
574
580
|
}
|
|
575
581
|
/**
|
|
576
582
|
* The document layer. Render the nodes inside `<g transform={transform}>` and `defs` in a
|
package/dist/vector/types.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GenerationProvenance } from '../generation/provenance.cjs';
|
|
2
2
|
import type { CanvasGradientDef } from '../canvas/gradient.cjs';
|
|
3
|
+
import type { CanvasBrushPaint } from '../canvas/brushTypes.cjs';
|
|
3
4
|
import type { WarpMesh, WarpStyle } from '../geom/types.cjs';
|
|
4
5
|
import type { GrainPattern } from '../paint/grain.cjs';
|
|
5
6
|
import type { Brush } from '../brushes/types.cjs';
|
|
@@ -282,7 +283,20 @@ export interface VectorBrushstroke {
|
|
|
282
283
|
seed?: number;
|
|
283
284
|
/** The paper the grain comes from (with `seed`); `null` for no grain. */
|
|
284
285
|
paper?: VectorBrushstrokePaper | null;
|
|
286
|
+
/**
|
|
287
|
+
* Gradient paint sampled dab by dab along the path, instead of the layer's colour (which still
|
|
288
|
+
* gives the alpha and fills `paint` stops): by distance travelled (document units), pressure,
|
|
289
|
+
* tilt, direction, across the tip or at random. Without it, a gradient layer paint is laid
|
|
290
|
+
* along, across or within the stroke (its `strokeMode`), and a brush with its own gradient
|
|
291
|
+
* paints that.
|
|
292
|
+
*/
|
|
293
|
+
paint?: VectorBrushstrokePaint;
|
|
285
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* A brushstroke's gradient paint (the paint engine's `PaintSource`, as canvas brushed strokes take
|
|
297
|
+
* it: `CanvasBrushPaint`). The `velocity` and `time` mappings are not allowed: paths have no timing.
|
|
298
|
+
*/
|
|
299
|
+
export type VectorBrushstrokePaint = CanvasBrushPaint;
|
|
286
300
|
/** One stroke of a path's stroke stack (`VectorStyle.strokes`): a paint plus its own stroke settings. */
|
|
287
301
|
export interface VectorStrokeLayer extends VectorPaintLayer, VectorStrokeSettings {
|
|
288
302
|
/** Default `paint`. See `VectorStrokeLayerKind`. */
|
package/dist/vector/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GenerationProvenance } from '../generation/provenance.js';
|
|
2
2
|
import type { CanvasGradientDef } from '../canvas/gradient.js';
|
|
3
|
+
import type { CanvasBrushPaint } from '../canvas/brushTypes.js';
|
|
3
4
|
import type { WarpMesh, WarpStyle } from '../geom/types.js';
|
|
4
5
|
import type { GrainPattern } from '../paint/grain.js';
|
|
5
6
|
import type { Brush } from '../brushes/types.js';
|
|
@@ -282,7 +283,20 @@ export interface VectorBrushstroke {
|
|
|
282
283
|
seed?: number;
|
|
283
284
|
/** The paper the grain comes from (with `seed`); `null` for no grain. */
|
|
284
285
|
paper?: VectorBrushstrokePaper | null;
|
|
286
|
+
/**
|
|
287
|
+
* Gradient paint sampled dab by dab along the path, instead of the layer's colour (which still
|
|
288
|
+
* gives the alpha and fills `paint` stops): by distance travelled (document units), pressure,
|
|
289
|
+
* tilt, direction, across the tip or at random. Without it, a gradient layer paint is laid
|
|
290
|
+
* along, across or within the stroke (its `strokeMode`), and a brush with its own gradient
|
|
291
|
+
* paints that.
|
|
292
|
+
*/
|
|
293
|
+
paint?: VectorBrushstrokePaint;
|
|
285
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* A brushstroke's gradient paint (the paint engine's `PaintSource`, as canvas brushed strokes take
|
|
297
|
+
* it: `CanvasBrushPaint`). The `velocity` and `time` mappings are not allowed: paths have no timing.
|
|
298
|
+
*/
|
|
299
|
+
export type VectorBrushstrokePaint = CanvasBrushPaint;
|
|
286
300
|
/** One stroke of a path's stroke stack (`VectorStyle.strokes`): a paint plus its own stroke settings. */
|
|
287
301
|
export interface VectorStrokeLayer extends VectorPaintLayer, VectorStrokeSettings {
|
|
288
302
|
/** Default `paint`. See `VectorStrokeLayerKind`. */
|
package/package.json
CHANGED
|
@@ -162,6 +162,7 @@ refuse.
|
|
|
162
162
|
| `update_effect` | Make an applied effect again with new `values`, in the same place (`effect` is its instance id). |
|
|
163
163
|
| `remove_effect` | Remove an applied effect: its commands, shots it alone filled and a vector effect's group. |
|
|
164
164
|
| `add_vector_effect` | Add a vector effect's own picture as an artwork group (fitted into `box`) with its motion as new shots. For an effect that draws along a path (`search_effects` `accepts: ["path"]`: a signature, a route), `path: { node }` runs it along a path node and lands it on the node, `path: { text }` writes words. Use it when the effect should trace the path itself; use `follow` or a draw-on to move or reveal your own art. Returns the instance and group ids. |
|
|
165
|
+
| `set_vector_effect_path` | Give a vector effect already added (`instance` from `add_vector_effect` or `list_applied_effects`) a new path in place: `path: { node }` runs it along a path node and lands it on the node, `path: { text }` writes words and keeps the picture where it was. Call it after reshaping the node an effect runs along (the path is a copy), or to switch between a node and words; clear the path with `update_effect` setting the path control to `""`. One undo step. Returns the instance, the `control` set and its new path data `value`. |
|
|
165
166
|
| `list_camera_moves` | List the provider's camera moves for a `role` (`transition`: how the camera gets into a shot; `hold`: how it moves while the shot holds), with `durationMs` and `cut`. Returns `available: false` without camera moves. Call before `set_shot_camera_move`; `describe_effect` gives a move's controls and presets. |
|
|
166
167
|
| `set_shot_camera_move` | Give a shot a camera move (`shot`, `role`, `move`, optional `ms` for a transition, `preset`, `values`): it is saved on the shot's camera as `in` or `during`. Returns the shot's camera and the `window` (ms) the move plays in. A wrong-role id is refused naming the moves that fit. |
|
|
167
168
|
| `clear_shot_camera_move` | Remove a shot's move for a `role`, keeping its framing. Returns the shot's camera (null when nothing is left). |
|
|
@@ -21,7 +21,7 @@ built-in presets (read-only) and the user's brushes, shared by every editor that
|
|
|
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`). |
|
|
24
|
-
| 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. |
|
|
24
|
+
| 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
25
|
|
|
26
26
|
How media map to facets: a **pencil** or **charcoal** is `dry` with high `grain` and tilt;
|
|
27
27
|
**ink** is a hard round tip with pressure to size (a pen thins with velocity); **watercolour**
|
|
@@ -43,7 +43,7 @@ paints without (warnings), each with a fix; lists and writes use the current hos
|
|
|
43
43
|
| Paint editor (`paint`) | Everything. |
|
|
44
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
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`. |
|
|
46
|
-
| Vector strokes (`vector`) | As canvas,
|
|
46
|
+
| 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
47
|
|
|
48
48
|
Every host lists the presets its profile admits and the library's saved brushes it admits, and
|
|
49
49
|
each registers these tools with its own profile, so `list_brush_presets` shows that host's brushes.
|
|
@@ -26,8 +26,9 @@ This skill is the method. `pixerate-brushes` has the full tool reference.
|
|
|
26
26
|
|
|
27
27
|
Ask when you cannot tell from the request; say what you assumed when you can.
|
|
28
28
|
|
|
29
|
-
- **Host:** which editor will use it (paint by default; canvas
|
|
30
|
-
dab brushes, the
|
|
29
|
+
- **Host:** which editor will use it (paint by default; canvas strokes take only dry dab brushes,
|
|
30
|
+
vector strokes dry and wet dab brushes, the Mixer Brush, smudge and blender; the image editor no
|
|
31
|
+
wet, thick or particle brushes).
|
|
31
32
|
- **Medium and character:** what it imitates (pencil, ink, chalk, watercolour, marker…), and
|
|
32
33
|
the size, softness and texture.
|
|
33
34
|
- **Colour:** a default colour or palette, or the user's own colour (the default).
|
|
@@ -53,7 +54,8 @@ Ask when you cannot tell from the request; say what you assumed when you can.
|
|
|
53
54
|
| Situation | Approach |
|
|
54
55
|
| --- | --- |
|
|
55
56
|
| A colour variant of a preset | `basedOn` it, set `colour.default` (and a `palette`), keep everything else. |
|
|
56
|
-
| For canvas
|
|
57
|
+
| For canvas strokes | Base on a dry preset (pencil, pastel, charcoal, marker, ink); no wet surface, particles, stickers or tools; no light. |
|
|
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. |
|
|
57
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. |
|
|
58
60
|
| A texture (chalk, charcoal, dry brush) | Raise `behaviour.grain` (0.8..1) and add `dynamics.sizeJitter`; test on rough paper. |
|
|
59
61
|
| A light brush (neon, glow) | `light.amount`, and paint it on dark paper; a highlighter keeps `light.spill.radius` 0. |
|
|
@@ -80,7 +82,8 @@ basedOn: "highlighter", colour: { default: "#ff6ec7" } }`, then `check_brush`.
|
|
|
80
82
|
- **Starting from nothing.** A brush without `basedOn` gets engine defaults (a hard round dab);
|
|
81
83
|
it rarely looks like the medium asked for.
|
|
82
84
|
- **A host that refuses the base.** A wet or particle preset can't be the base of a canvas
|
|
83
|
-
brush; set `behaviour.surface` to `dry`
|
|
85
|
+
brush, nor a thick (impasto) preset of a vector one; set `behaviour.surface` to `dry` (vector
|
|
86
|
+
also takes `wet`) or start from a dry preset.
|
|
84
87
|
- **Lists replace.** Giving `colour.palette` or `tip.stamps` replaces the whole list; include
|
|
85
88
|
every entry you want.
|
|
86
89
|
- **Changing a built-in.** `update_brush` refuses built-ins; duplicate first.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
|
-
"prompt": "A teammate's brush team-
|
|
2
|
+
"prompt": "A teammate's brush team-knife is in the library, but it won't work for vector brushstrokes. Make a copy called team-knife-vector that does, and leave theirs as it is.",
|
|
3
3
|
"fixture": {
|
|
4
4
|
"editor": "brushes",
|
|
5
|
-
"setup": [{ "tool": "create_brush", "args": { "id": "team-
|
|
5
|
+
"setup": [{ "tool": "create_brush", "args": { "id": "team-knife", "name": "Team knife", "basedOn": "palette-knife", "tags": ["team"] } }]
|
|
6
6
|
},
|
|
7
7
|
"checks": [
|
|
8
|
-
{ "why": "the copy works in the vector editor", "tool": "check_brush", "args": { "id": "team-
|
|
9
|
-
{ "why": "the copy keeps the
|
|
10
|
-
{ "why": "the teammate's brush still
|
|
8
|
+
{ "why": "the copy works in the vector editor", "tool": "check_brush", "args": { "id": "team-knife-vector", "host": "vector" }, "expect": { "ok": true } },
|
|
9
|
+
{ "why": "the copy keeps the knife's tip", "tool": "describe_brush", "args": { "id": "team-knife-vector" }, "expect": { "brush": { "tip": { "size": 48, "roundness": 0.18 } } } },
|
|
10
|
+
{ "why": "the teammate's brush still lays thick paint", "tool": "describe_brush", "args": { "id": "team-knife" }, "expect": { "brush": { "behaviour": { "surface": "thick" } } } }
|
|
11
11
|
],
|
|
12
12
|
"solution": [
|
|
13
|
-
{ "tool": "check_brush", "args": { "id": "team-
|
|
14
|
-
{ "tool": "create_brush", "args": { "id": "team-
|
|
15
|
-
{ "tool": "check_brush", "args": { "id": "team-
|
|
13
|
+
{ "tool": "check_brush", "args": { "id": "team-knife", "host": "vector" } },
|
|
14
|
+
{ "tool": "create_brush", "args": { "id": "team-knife-vector", "name": "Team knife (vector)", "basedOn": "team-knife", "behaviour": { "surface": "wet" } } },
|
|
15
|
+
{ "tool": "check_brush", "args": { "id": "team-knife-vector", "host": "vector" } }
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -100,7 +100,14 @@ you to. Withdraw stale ones with `reject_proposal`: when the user changes what a
|
|
|
100
100
|
stroke always looks the same, and neighbouring strokes share one sheet of paper. Pick the brush
|
|
101
101
|
for the look, then the colour; for a sketch, use one or two brushes rather than all of them.
|
|
102
102
|
A brush with a default colour (ballpoint blue, highlighter yellow, chalk) paints in it when
|
|
103
|
-
you pass no `color`; pass `color` to use another.
|
|
103
|
+
you pass no `color`; pass `color` to use another. Light / dark defaults (chalk) resolve for
|
|
104
|
+
the canvas's colour scheme (`canvas.setColorScheme`; the host usually matches its theme).
|
|
105
|
+
- **Setting up the pen for the person, not drawing.** `canvas.selectBrush` chooses the brush the
|
|
106
|
+
person draws with by hand, as the brush picker does: it takes the brush's default colour unless
|
|
107
|
+
they locked theirs (`canvas.setColorLocked`, "Keep my colour") or you pass `keepColour`. A
|
|
108
|
+
default taken this way follows the scheme until another colour is set. Respect a lock the
|
|
109
|
+
person set; don't unlock it to change their colour. These are editor state, not undo steps,
|
|
110
|
+
and don't affect `canvas.drawFreehand`, which takes its own `brush` and `color`.
|
|
104
111
|
- **Annotate with gestures, not points.** To mark up work the way a designer marks up a print,
|
|
105
112
|
use the gesture commands (`canvas.circle`, `canvas.underline`, `canvas.arrow`,
|
|
106
113
|
`canvas.bracket`, `canvas.strike`, `canvas.cross`, `canvas.check`) with node ids
|
|
@@ -254,6 +261,9 @@ character: seeded jitter and the paper grain they catch) and, when a width was c
|
|
|
254
261
|
| Command | Use it to |
|
|
255
262
|
| --- | --- |
|
|
256
263
|
| `canvas.drawFreehand` | Draw a pen or highlighter stroke through `points` (`[x, y]` pairs in canvas units, in drawing order; one undo step). `tool` picks the defaults (`pen`: blue, width 3; `highlighter`: yellow, width 24, opacity 0.35); `color`, `width`, `opacity` override them (with a `brush` and no `color`, the brush's default colour if it has one; with a `brush`, `width` is the brush diameter and defaults to the preset's own size). Pass `brush` (a preset or saved brush id from `canvas.listBrushes`, or tip settings) to paint it with a dry brush, plus `pressure` / `tiltX` / `tiltY` profiles spread along its length (`[0.2, 1, 0.3]` swells in the middle). Add `paint` (only with `brush`) for gradient paint that changes colour along the stroke: `{ "type": "gradient", "stops": [...], "map": { "by": "distance", "length": 200 } }` (length in canvas units), or `by` `pressure`, `tilt`, `direction`, `across-tip`, `random`. Returns the node `id`, its `bounds` and the stored `brush` (with `paint` normalised: defaults filled in, colours lowercased). |
|
|
264
|
+
| `canvas.selectBrush` | Choose the brush the person draws with by hand (`brushId` from `canvas.listBrushes`, or `null` for a plain vector stroke), at its own size, taking its default colour unless the colour is locked or `keepColour`. Draws nothing. Returns `{ brush, color, colorScheme, colorLocked, colorFollowsScheme }`. |
|
|
265
|
+
| `canvas.setColorLocked` | Lock (`locked: true`) or unlock the hand-drawing colour ("Keep my colour"): while locked, `canvas.selectBrush` keeps it. Returns the same settings as `canvas.selectBrush`; call it (or `canvas.selectBrush`) to read whether the person locked it. |
|
|
266
|
+
| `canvas.setColorScheme` | Set `scheme` `light` or `dark`: picks the side of light / dark default colours for `canvas.selectBrush` and `canvas.drawFreehand`; a colour taken from such a default follows, strokes already drawn keep theirs. Usually the host's job. Returns the same settings as `canvas.selectBrush`. |
|
|
257
267
|
| `canvas.listBrushes` | Read-only: the brushes `canvas.drawFreehand` and the gestures accept as `brush`: the dry presets, then saved brushes from the brush library the canvas can paint (`id`, `name`, `category`, the brush's own `size`, which a stroke uses unless you pass `width`, and `builtin`). Call it before the first brushed stroke instead of guessing ids. |
|
|
258
268
|
|
|
259
269
|
Gestures draw one hand-drawn stroke node each (one undo step) through the same path as
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pixerate-image-editor
|
|
3
|
-
description: How to colour-correct, composite and retouch a photo in the Pixerate image editor through its agent tools - layers (pixel, adjustment, group, shape, type, annotation
|
|
3
|
+
description: How to colour-correct, composite and retouch a photo in the Pixerate image editor through its agent tools - layers (pixel, adjustment, group, shape, type, annotation, smart object; masks, clipping, blend modes, filters), 16/32-bit depth, colour management (profiles, proofing, CMYK, Lab), smart objects and smart filters, provider effects, layer effects, adjustments, selections and masks, Free Transform, crop, rotate, flip, painting and Mixer Brush, retouching (Clone Stamp, Healing, Spot Healing, Smudge, Dodge, Burn, Sponge, Blur, Sharpen, History Brush), undo, PSD, histogram and previews. Use when editing, grading, cropping, masking or retouching an image, adding effects, shapes or text, converting profiles or bit depth, transforming layers, or when list_layers, set_adjustments, add_layer_effect, apply_effect, transform_layer, add_text_layer, paint_stroke, clone_stamp, spot_heal, blur_stroke, sharpen_stroke, history_brush, set_bit_depth, convert_to_profile or import_psd are available.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Image editor
|
|
7
7
|
|
|
8
|
-
The image editor holds a layer stack over a canvas the size of the source image
|
|
8
|
+
The image editor holds a layer stack over a canvas the size of the source image (8-, 16- or
|
|
9
|
+
32-bit depth, with RGB, CMYK and Lab colour management, ICC profiles and soft proofing). Opening an
|
|
9
10
|
image gives one pixel layer, **Background**, whose pixels are the source and whose `develop`
|
|
10
11
|
filter holds the base adjustments (the base controls edit the develop filter of the active pixel
|
|
11
12
|
layer). Adjustment layers sit above it, each through its mask, opacity and blend mode, and
|
|
12
13
|
annotations are shape and type layers on top. Edits never touch the source pixels; `list_layers`
|
|
13
14
|
shows the whole stack. Pixel, group and smart object layers can carry live effects; a smart
|
|
14
|
-
object places contents through a transform and smart filters
|
|
15
|
+
object places contents through a transform and smart filters (including provider effects, which
|
|
16
|
+
also add generator and overlay effect layers); shape layers hold vector paths and
|
|
15
17
|
type layers live text, re-rendered on every change. There is also an optional selection and a
|
|
16
18
|
crop, rotation and flip. See `pixerate-agent-tools` for errors and batching.
|
|
17
19
|
|
|
@@ -95,9 +97,9 @@ Boxes, badges, arrows and callouts are shape layers (`add_shape_layer`), text is
|
|
|
95
97
|
(`add_text_layer`); both stay sharp and take effects, masks and blends. Read
|
|
96
98
|
[references/shapes-and-type.md](references/shapes-and-type.md) before drawing or editing either.
|
|
97
99
|
|
|
98
|
-
### Layer effects
|
|
100
|
+
### Layer and provider effects
|
|
99
101
|
|
|
100
|
-
Live per-layer
|
|
102
|
+
Live per-layer styles (shadows, glows, bevel, overlays, strokes): see [references/layer-effects.md](references/layer-effects.md). Provider filter smart filters and generator / overlay effect layers (`search_effects`, `describe_effect`, `apply_effect`, `add_effect_layer`): see [references/provider-effects.md](references/provider-effects.md).
|
|
101
103
|
|
|
102
104
|
### Paths and cutout edges
|
|
103
105
|
|
|
@@ -110,13 +112,15 @@ Keep outlines as paths (`make_work_path`, `add_path`) and edit their anchors: se
|
|
|
110
112
|
Paint on its own layer (`add_pixel_layer`), one stroke per call and one undo step, limited by a
|
|
111
113
|
selection or locked transparency. Read [references/painting.md](references/painting.md) first.
|
|
112
114
|
|
|
113
|
-
###
|
|
115
|
+
### Bit depth and colour management
|
|
114
116
|
|
|
115
|
-
|
|
117
|
+
Switch between 8-, 16- and 32-bit (float, linear light) with `set_bit_depth` (`references/photoshop-files.md`). For working space profiles (`assign_profile`, `convert_to_profile`), soft proofing (`set_proof_setup`) and CMYK / Lab print modes (`set_color_mode`, `convert_colors`), read [references/color-management.md](references/color-management.md).
|
|
116
118
|
|
|
117
119
|
### Retouching
|
|
118
120
|
|
|
119
|
-
Heal
|
|
121
|
+
Heal and clone on layers above the photo (`sample: "current-below"`); dodge, burn, sponge, blur
|
|
122
|
+
(`blur_stroke`), sharpen (`sharpen_stroke`) and History Brush (`history_brush`) change the pixels
|
|
123
|
+
they touch, so run them on a duplicate. Load
|
|
120
124
|
`pixerate-image-portrait-retouch`, and read [references/retouching.md](references/retouching.md) first.
|
|
121
125
|
|
|
122
126
|
### Photoshop files
|
|
@@ -136,11 +140,11 @@ in the source frame at the document's bit depth, colour mode and profile. Read
|
|
|
136
140
|
- **Blend modes for tone-only or colour-only changes:** `luminosity` applies a curves or
|
|
137
141
|
levels layer without shifting hue or saturation; `color` applies a tint without changing
|
|
138
142
|
brightness; `soft-light` / `overlay` for gentle contrast.
|
|
139
|
-
- **`pigment`
|
|
143
|
+
- **`pigment` and painterly modes mix like paint.** On a layer, a fill or a brush, `pigment` mixes the colour into
|
|
140
144
|
what is below as real paint would (Kubelka-Munk): blue into yellow gives green, white gives
|
|
141
145
|
tints, and opacity is the share of new paint (0.5 is half and half). Use it for glazes,
|
|
142
|
-
natural colour mixing and painterly strokes;
|
|
143
|
-
layers that must
|
|
146
|
+
natural colour mixing and painterly strokes; neither `pigment` nor the painterly modes (`watercolor`, `tint`, `highlight`, `shadow`) are Photoshop modes (`export_psd` writes them as Normal), so keep them off
|
|
147
|
+
layers that must stay editable in a PSD round trip. `pigment` costs about ten times a normal blend.
|
|
144
148
|
- **Name layers** (`name`) by intent ("Sky darken", "Warm skin"), so the stack stays readable.
|
|
145
149
|
- **Effects, transforms and smart objects** have their own best practices in
|
|
146
150
|
`references/layer-effects.md`, `references/free-transform.md` and `references/smart-objects.md`.
|
|
@@ -174,7 +178,7 @@ in the source frame at the document's bit depth, colour mode and profile. Read
|
|
|
174
178
|
| `measure_region` | Measure a rectangle of the composited image (`x`, `y`, `width`, `height` in natural pixels; default the crop, else the whole image) without a render: the `get_histogram` summary plus `meanColor` (hex) and `cast` (`redBlue`, `greenMagenta` in levels; within about ±4 is neutral). Check a neutral reference, skin, a background or clipping after each correction. |
|
|
175
179
|
| `render_preview` | See the edited image (crop, adjustments, layers, annotations) as a PNG, or with `layerId` one layer alone. `maxSide` 16..2048 px, default 512. Images cost tokens: render after a group of edits, use 512 for overall look and 1024+ to judge clipping, edges and masks. Fails in environments without rendering. |
|
|
176
180
|
| `inspect_psd` | Read a PSD / PSB (`data` base64) without opening it: size, `depth`, `colorMode`, `resolution`, every layer bottom first with `psdKind`, the `type` it would become (`smart`, `shape` and `type` for Photoshop smart objects, shapes and text) and `status` (`mapped`, `approximated`, `dropped`) with `notes`, and the import `warnings`. Call before `import_psd`. |
|
|
177
|
-
| `export_psd` | Save the document as
|
|
181
|
+
| `export_psd` | Save the document as a PSD in its colour mode (RGB, or CMYK / Lab channels after `set_color_mode`) with its profile, at its bit depth (RGB 8, 16 or 32; CMYK and Lab 8 or 16, so a 32-bit CMYK / Lab document is written at 16 with a warning; PSB above 30000 px), with layers, groups, adjustment layers and masks. Returns `data` (base64), `size` in bytes, `psb` and `warnings` (crop or rotation not applied, filters and depth masks baked, annotations rasterized or left out, Pigment blends written as Normal; painterly blends are written as Normal too, without a warning). Shape and type layers are written as real Photoshop shape and type layers. Changes nothing. |
|
|
178
182
|
| `get_transform_frame` | Before a transform: what it would move (`content`, `moved`: pixels, mask, selection), its `frame` (document bounds of the content), `corners` (top-left, top-right, bottom-right, bottom-left) and `center`. `meshColumns` / `meshRows` also return an identity warp `mesh` over the frame to edit for `warp_layer`. Changes nothing. |
|
|
179
183
|
| `get_smart_object` | Read a smart object: `contents` (`id` shared by linked instances, `name`, `kind` raster or document, `width` / `height`, `decoded`, `fileType`, `linkedPath`, `instances`), `placement` (`corners`, `warp` in contents px, `interpolation`, and when `affine` the `scaleX` / `scaleY` in percent of the contents, `rotate`, `skewX`, `center`, `bounds`) and `smartFilters` (`enabled`, `filters` bottom to top with ids, settings, `blend`, `opacity`; kind `psd` is a Photoshop filter kept but not drawn; the filter `mask`). Call before changing a smart object. |
|
|
180
184
|
| `list_fonts` | Read the font families type layers can use here (generic families always work) and which shaper draws them. Call before choosing a font. |
|
|
@@ -381,13 +385,7 @@ The host may add the shared document tools (see `pixerate-agent-tools`). An imag
|
|
|
381
385
|
## Pitfalls
|
|
382
386
|
|
|
383
387
|
- Agent playback (if on) opens each write's panel, then traces `points`, drags boxes or visits the layers and sliders named; results are unchanged.
|
|
384
|
-
-
|
|
385
|
-
- `bevel-emboss` has no `blend` / `opacity`: it uses `highlightBlend`, `highlightOpacity`,
|
|
386
|
-
`shadowBlend` and `shadowOpacity`. Inner shadows and inner glows use `choke`, not `spread`.
|
|
387
|
-
- Glows paint a colour or a gradient, never a pattern; strokes take all three. Pattern effects
|
|
388
|
-
need a pattern id from `list_layer_effects.patterns`; an unknown id paints nothing.
|
|
389
|
-
- Effect angles are where the light comes *from*: 120° (top left) casts a shadow down and to
|
|
390
|
-
the right. With `useGlobalLight` true an effect's own `angle` is ignored.
|
|
388
|
+
- Domain-specific pitfalls live in their references: layer styles in [references/layer-effects.md](references/layer-effects.md), provider effects in [references/provider-effects.md](references/provider-effects.md), painting and the Mixer Brush in [references/painting.md](references/painting.md), retouching in [references/retouching.md](references/retouching.md), shapes and text in [references/shapes-and-type.md](references/shapes-and-type.md), smart objects in [references/smart-objects.md](references/smart-objects.md), Free Transform in [references/free-transform.md](references/free-transform.md), colour management in [references/color-management.md](references/color-management.md), and PSD in [references/photoshop-files.md](references/photoshop-files.md).
|
|
391
389
|
- A layer's `kind` cannot change; to switch kinds add a new layer and remove the old one.
|
|
392
390
|
Curves points, `colorize` and colours are only set when the layer is added, so get them
|
|
393
391
|
right in `add_adjustment_layer` (or replace the layer).
|
|
@@ -395,41 +393,7 @@ The host may add the shared document tools (see `pixerate-agent-tools`). An imag
|
|
|
395
393
|
`locks` only when the user wants that layer changed.
|
|
396
394
|
- `merge_down`, `merge_visible` and `flatten_image` merge annotation layers only in a browser
|
|
397
395
|
(they need a canvas); elsewhere they fail and say so.
|
|
398
|
-
-
|
|
399
|
-
- `paint_stroke`, `fill_pixels` and `clear_pixels` need a visible pixel layer (or a layer with a
|
|
400
|
-
raster mask and `channel: "mask"`); adjustment, group, shape, type, annotation and smart object layers can
|
|
401
|
-
only be painted through their masks (and a smart object through `channel: "filter-mask"`).
|
|
402
|
-
To paint a smart object's pixels, `edit_smart_object_contents` or rasterize it. A layer with
|
|
403
|
-
`locks.pixels` refuses paint.
|
|
404
|
-
- Text ranges count UTF-16 code units (an emoji is two). Point text grows from its origin: centred
|
|
405
|
-
text is centred on `x`. Type cannot be distorted, put in perspective or warped; it can be scaled,
|
|
406
|
-
rotated and skewed. Where no font shaper exists (a server without one), type layers keep their
|
|
407
|
-
stored pixels and edits are refused with a reason.
|
|
408
|
-
- Shape strokes are not layer-effect strokes: `stroke` on `add_shape_layer` / `update_shape`
|
|
409
|
-
follows the path (and its dashes and caps); `add_layer_effect` `stroke` outlines the rendered
|
|
410
|
-
pixels. Arrowheads belong to `line` live shapes (their `width` and `length` are pixels), not to
|
|
411
|
-
strokes. A shape drawn over an annotation migrated from an old document (a shape layer with an
|
|
412
|
-
`annotation` in `list_layers`) stops being that annotation once you edit it as a shape.
|
|
413
|
-
- Shapes render up to 512 px beyond the canvas; moving one in from far outside draws it again
|
|
414
|
-
from its paths, so nothing is lost.
|
|
415
|
-
- While contents are open (`edit_smart_object_contents`), `list_layers` and every tool see the
|
|
416
|
-
contents, not the document, and `export_psd` / saving write the document without the open
|
|
417
|
-
edits. Close with `close_smart_object_contents` before anything else.
|
|
418
|
-
- Smart filters run over the canvas, like layer filters: a blur clamps at the canvas edge, and a
|
|
419
|
-
smart object is drawn only up to 512 px beyond the canvas. `get_transform_frame` on a smart
|
|
420
|
-
object returns the contents' rectangle (contents px) as the `frame`, and a warp `mesh` in
|
|
421
|
-
contents px.
|
|
422
|
-
- `mix_colors` predicts a mix; it does not paint. To paint the mix, pass `blend: "pigment"` to
|
|
423
|
-
`paint_stroke` (in `brush`) or `fill_pixels`, or set it on a layer.
|
|
424
|
-
- `pigment` has no PSD equivalent: `export_psd` writes those layers as Normal (the merged image
|
|
425
|
-
keeps the look) and says so in `warnings`, naming the layers. `import_psd` never produces it.
|
|
426
|
-
Over transparent pixels there is nothing to mix with, so it lays the colour down as Normal.
|
|
427
|
-
- The Mixer Brush ignores `brush.blend` (including `pigment`; use its own `mixer.mixing` instead) and the opacity ceiling: each dab lays paint at
|
|
428
|
-
`flow × opacity` over the pixels as they are now, so overlapping dabs build up. At `flow` 1
|
|
429
|
-
each dab covers what is under it, the pickup then sees mostly the brush's own paint, and the
|
|
430
|
-
stroke drifts towards the loaded colour; lower the flow for more blending.
|
|
431
|
-
- An empty, dry mixer (no reservoir, `wet` 0) paints nothing; the call succeeds with
|
|
432
|
-
`bounds: null`. A mixer stroke over transparent pixels has nothing to pick up.
|
|
396
|
+
- `pigment` and the painterly blend modes (`watercolor`, `tint`, `highlight`, `shadow`) have no Photoshop mode in the image editor's PSD exporter: `export_psd` writes those layers as Normal (the merged image keeps the composited look; only `pigment` adds a warning, naming the layers). `import_psd` never produces them.
|
|
433
397
|
- `export_psd` is in the source frame: a crop or rotation is not in the file (the warnings say
|
|
434
398
|
so). Crop with `set_crop` only for PNG / JPEG output, or flatten the look you need first.
|
|
435
399
|
- PSD opacity, fill and mask density come in as whole percents (Photoshop stores bytes), so a
|
|
@@ -444,19 +408,10 @@ The host may add the shared document tools (see `pixerate-agent-tools`). An imag
|
|
|
444
408
|
Do not keep raising it; correct the green-magenta cast with a `colorBalance` layer instead.
|
|
445
409
|
- Base `opacity` fades the whole image, not an adjustment. Base `blur` blurs a whole layer (the
|
|
446
410
|
Background by default, before the adjustment layers; in older documents with blur and
|
|
447
|
-
adjustment layers, the output after them).
|
|
411
|
+
adjustment layers, the output after them). For local softening use `blur_stroke`.
|
|
448
412
|
- New adjustment layers go above the other adjustment layers and below annotations, so they
|
|
449
413
|
never tint arrows, labels or watermarks. `list_layers` shows where each one went.
|
|
450
414
|
- `invert` and `threshold` are destructive-looking creative effects; never use them for a
|
|
451
415
|
correction the user did not ask for. Posterize `levels` below ~8 bands visibly.
|
|
452
|
-
- Transforms refuse hidden layers, layers with `locks.position` or `locks.pixels`, and adjustment,
|
|
453
|
-
annotation and group layers (transform a layer's mask with `channel: "mask"` after unlinking
|
|
454
|
-
it). A result larger than about 11 600 × 11 600 px is refused.
|
|
455
|
-
- `transform_layer` scale fields are percent (100 = unchanged), not factors; `rotate` is degrees
|
|
456
|
-
clockwise. `corners` that cross or fold through the horizon are refused: keep the quad convex.
|
|
457
|
-
- With a selection, `content: "auto"` (the default) moves only the selected pixels, not the
|
|
458
|
-
whole layer. Pass `content: "layer"` to move everything regardless of the selection.
|
|
459
|
-
- A Background transformed smaller leaves transparent canvas around it; fill it with a layer
|
|
460
|
-
below or crop afterwards.
|
|
461
416
|
- Opacity values are 0..1, not percent. Curves and levels points are 0..255 levels; levels
|
|
462
417
|
`gamma` is 0.1..9.99 (1 = neutral); hue is degrees -180..180.
|
|
@@ -38,6 +38,7 @@ means sRGB. The viewport assumes an sRGB display and converts other working spac
|
|
|
38
38
|
`unconvertedLayerIds`: convert inside them (`edit_smart_object_contents`) if the look matters.
|
|
39
39
|
- Images opened from a URL or file in the browser arrive already converted to sRGB by the
|
|
40
40
|
browser, so their own profile is not kept; PSDs keep theirs (resource 1039).
|
|
41
|
-
- `export_psd`
|
|
41
|
+
- `export_psd` embeds the profile (the working space for RGB, the press profile for CMYK; Lab
|
|
42
|
+
files carry none); PNG and JPEG exports embed it when it is not sRGB.
|
|
42
43
|
- The first proof or conversion with `coated-cmyk` builds that profile, which takes a second or
|
|
43
44
|
two.
|
|
@@ -31,3 +31,15 @@ How to move, scale, rotate, skew, distort and warp layers, selected pixels and m
|
|
|
31
31
|
- **Scale proportionally** unless asked to stretch: give `scaleX` and `scaleY` the same value.
|
|
32
32
|
Keep the subject in frame: after a scale about `center` the layer can run past the canvas,
|
|
33
33
|
which `bounds` in the result shows.
|
|
34
|
+
|
|
35
|
+
## Pitfalls
|
|
36
|
+
|
|
37
|
+
- Transforms refuse hidden layers, layers with `locks.position` or `locks.pixels`, and adjustment,
|
|
38
|
+
annotation and group layers (transform a layer's mask with `channel: "mask"` after unlinking
|
|
39
|
+
it). A result larger than about 11 600 × 11 600 px is refused.
|
|
40
|
+
- `transform_layer` scale fields are percent (100 = unchanged), not factors; `rotate` is degrees
|
|
41
|
+
clockwise. `corners` that cross or fold through the horizon are refused: keep the quad convex.
|
|
42
|
+
- With a selection, `content: "auto"` (the default) moves only the selected pixels, not the
|
|
43
|
+
whole layer. Pass `content: "layer"` to move everything regardless of the selection.
|
|
44
|
+
- A Background transformed smaller leaves transparent canvas around it; fill it with a layer
|
|
45
|
+
below or crop afterwards.
|
|
@@ -34,3 +34,13 @@ Read this before `add_layer_effect`, `update_layer_effect`, `set_global_light` o
|
|
|
34
34
|
layer `opacity` fades the effects too.
|
|
35
35
|
- **Prefer an effect over painted pixels** for shadows, glows, outlines and colour fills of a
|
|
36
36
|
shape: it follows later edits and stays adjustable.
|
|
37
|
+
|
|
38
|
+
## Pitfalls
|
|
39
|
+
|
|
40
|
+
- Effects need a shape: on an empty layer they draw nothing. They cannot go on adjustment layers. A clipped layer's effects stay inside the layer it is clipped to.
|
|
41
|
+
- `bevel-emboss` has no `blend` / `opacity`: it uses `highlightBlend`, `highlightOpacity`,
|
|
42
|
+
`shadowBlend` and `shadowOpacity`. Inner shadows and inner glows use `choke`, not `spread`.
|
|
43
|
+
- Glows paint a colour or a gradient, never a pattern; strokes take all three. Pattern effects
|
|
44
|
+
need a pattern id from `list_layer_effects.patterns`; an unknown id paints nothing.
|
|
45
|
+
- Effect angles are where the light comes *from*: 120° (top left) casts a shadow down and to
|
|
46
|
+
the right. With `useGlobalLight` true an effect's own `angle` is ignored.
|
|
@@ -43,3 +43,20 @@ Read this before `mix_colors`, a `paint_stroke` with `tool: "mixer"`, or gradien
|
|
|
43
43
|
"gradient", stops, map }`, or `paint_stroke` `paint` for one stroke (brush only). `map.by`
|
|
44
44
|
`distance` (default 300 px, mirrored) for drag-it-out colour, `pressure`, `direction`,
|
|
45
45
|
`across-tip`, `random`; stops may be `"paint"` / `"secondary"` (foreground / background).
|
|
46
|
+
|
|
47
|
+
## Pitfalls
|
|
48
|
+
|
|
49
|
+
- `paint_stroke`, `fill_pixels` and `clear_pixels` need a visible pixel layer (or a layer with a
|
|
50
|
+
raster mask and `channel: "mask"`); adjustment, group, shape, type, annotation and smart object layers can
|
|
51
|
+
only be painted through their masks (and a smart object through `channel: "filter-mask"`).
|
|
52
|
+
To paint a smart object's pixels, `edit_smart_object_contents` or rasterize it. A layer with
|
|
53
|
+
`locks.pixels` refuses paint.
|
|
54
|
+
- `mix_colors` predicts a mix; it does not paint. To paint the mix, pass `blend: "pigment"` to
|
|
55
|
+
`paint_stroke` (in `brush`) or `fill_pixels`, or set it on a layer.
|
|
56
|
+
- `pigment` and the painterly blend modes (`watercolor`, `tint`, `highlight`, `shadow`) have no Photoshop mode in the image editor's PSD exporter: `export_psd` writes those layers as Normal (the merged image keeps the look; only `pigment` adds a warning, naming the layers). `import_psd` never produces them. Over transparent pixels there is nothing for `pigment` to mix with, so it lays the colour down as Normal.
|
|
57
|
+
- The Mixer Brush ignores `brush.blend` (including `pigment`; use its own `mixer.mixing` instead) and the opacity ceiling: each dab lays paint at
|
|
58
|
+
`flow × opacity` over the pixels as they are now, so overlapping dabs build up. At `flow` 1
|
|
59
|
+
each dab covers what is under it, the pickup then sees mostly the brush's own paint, and the
|
|
60
|
+
stroke drifts towards the loaded colour; lower the flow for more blending.
|
|
61
|
+
- An empty, dry mixer (no reservoir, `wet` 0) paints nothing; the call succeeds with
|
|
62
|
+
`bounds: null`. A mixer stroke over transparent pixels has nothing to pick up.
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
(kind `psd`): hide, reorder, re-blend or remove them, and `export_psd` writes them back.
|
|
41
41
|
5. **`export_psd` writes the stack as it is**, in the source frame: crop and rotation are not
|
|
42
42
|
applied, layer filters and depth masks are baked, annotation layers are rasterized (only in
|
|
43
|
-
a browser). Effects are written as Photoshop layer styles: an effects block opened from a PSD
|
|
43
|
+
a browser), and `pigment` or painterly blend modes (`watercolor`, `tint`, `highlight`, `shadow`) are written as Normal (the merged image keeps their composited look; only `pigment` adds a warning, naming the layers). Effects are written as Photoshop layer styles: an effects block opened from a PSD
|
|
44
44
|
goes back byte for byte while its effects are unchanged, and the patterns effects use (the
|
|
45
45
|
built-in ones too) are embedded. Only the first outer glow, inner glow, bevel, satin and
|
|
46
46
|
pattern overlay of a layer fit in a PSD. Smart objects are written as smart objects (an
|
|
@@ -72,3 +72,17 @@ upright-Latin runs) and goes back out as vertical type. `get_text_layer` reports
|
|
|
72
72
|
and `missingFonts` for those: if a font is missing, edits draw with a fallback, so tell the user
|
|
73
73
|
before editing such text, or pick an available font with `set_text_style`. `export_psd` writes both
|
|
74
74
|
kinds back as Photoshop layers; unchanged ones are written byte for byte as they were read.
|
|
75
|
+
|
|
76
|
+
## Pitfalls
|
|
77
|
+
|
|
78
|
+
- Text ranges count UTF-16 code units (an emoji is two). Point text grows from its origin: centred
|
|
79
|
+
text is centred on `x`. Type cannot be distorted, put in perspective or warped; it can be scaled,
|
|
80
|
+
rotated and skewed. Where no font shaper exists (a server without one), type layers keep their
|
|
81
|
+
stored pixels and edits are refused with a reason.
|
|
82
|
+
- Shape strokes are not layer-effect strokes: `stroke` on `add_shape_layer` / `update_shape`
|
|
83
|
+
follows the path (and its dashes and caps); `add_layer_effect` `stroke` outlines the rendered
|
|
84
|
+
pixels. Arrowheads belong to `line` live shapes (their `width` and `length` are pixels), not to
|
|
85
|
+
strokes. A shape drawn over an annotation migrated from an old document (a shape layer with an
|
|
86
|
+
`annotation` in `list_layers`) stops being that annotation once you edit it as a shape.
|
|
87
|
+
- Shapes render up to 512 px beyond the canvas; moving one in from far outside draws it again
|
|
88
|
+
from its paths, so nothing is lost.
|
|
@@ -35,3 +35,13 @@ How to work with smart objects in the image editor (see the main skill for the t
|
|
|
35
35
|
the user may want to mask, blend or reorder them later.
|
|
36
36
|
- **Linked or not**: duplicate a smart object `linked: true` for repeated elements that must stay
|
|
37
37
|
identical (a logo placed twice); use `linked: false` when the copies will be edited apart.
|
|
38
|
+
|
|
39
|
+
## Pitfalls
|
|
40
|
+
|
|
41
|
+
- While contents are open (`edit_smart_object_contents`), `list_layers` and every tool see the
|
|
42
|
+
contents, not the document, and `export_psd` / saving write the document without the open
|
|
43
|
+
edits. Close with `close_smart_object_contents` before anything else.
|
|
44
|
+
- Smart filters run over the canvas, like layer filters: a blur clamps at the canvas edge, and a
|
|
45
|
+
smart object is drawn only up to 512 px beyond the canvas. `get_transform_frame` on a smart
|
|
46
|
+
object returns the contents' rectangle (contents px) as the `frame`, and a warp `mesh` in
|
|
47
|
+
contents px.
|
|
@@ -321,7 +321,7 @@ Listing, saving, sharing and previewing brushes are the brush library's tools (`
|
|
|
321
321
|
| Tool | Use |
|
|
322
322
|
| --- | --- |
|
|
323
323
|
| `paint_stroke` | Paint one stroke through `points` (document px; `pressure` 0..1, `t` ms, `tiltX` / `tiltY` or `altitude` / `azimuth`, `twist`) with `brushId` (default the active brush), optional per-stroke `brush` facet changes (as `set_brush` takes), `color` or `paint` (a gradient for this stroke), `layerId`, `seed`, `snapToPerspective`. The symmetry guide adds its copies; a sampling tracing image supplies the colour when `color` is missing. Returns `layerId`, `bounds`, `dabs`, `strokeId` and, for brushes that pick up paint, `mixerLoad` (what the brush carries now). Refused on locked, hidden or group layers, with the fix in the message. |
|
|
324
|
-
| `stroke_path` | Brush SVG path data (`path`, document px; M, L, C, Q, A, Z…) with the active brush or `brushId` / `brush`, as if drawn along it by hand: each subpath one recorded stroke, sampled every `spacing` px (default 2), with a `pressure` profile spread along each subpath (`[0.2, 1, 0.2]` tapers both ends). One undo step. Returns `layerId`, `bounds`, `dabs` and `strokeIds` (for `replay_strokes`, `update_stroke`). Use it for clean curves, outlines of shapes and lettering guides instead of working out points; use `paint_stroke` when the marks need
|
|
324
|
+
| `stroke_path` | Brush SVG path data (`path`, document px; M, L, C, Q, A, Z…) with the active brush or `brushId` / `brush`, as if drawn along it by hand: each subpath one recorded stroke, sampled every `spacing` px (default 2), with a `pressure` profile spread along each subpath (`[0.2, 1, 0.2]` tapers both ends) and optional `speed` (px/ms, stamps each sample with `t`). With an agent director, each subpath is painted live in turn. One undo step. Returns `layerId`, `bounds`, `dabs` and `strokeIds` (for `replay_strokes`, `update_stroke`). Use it for clean curves, outlines of shapes and lettering guides instead of working out points; use `paint_stroke` when the marks need variable timing or tilt. |
|
|
325
325
|
| `list_strokes` | Read the recorded strokes, oldest first (default the last 100): id, layer, brush, colour, point count, seed, bounds, `live`. With `ids`, their points too; with `layerId`, one layer's. With `live: true`, the editable strokes of stroke layers as they are now, bottom first: the ids for the stroke layer tools. |
|
|
326
326
|
| `get_live_stroke` | Read the stroke the user is painting right now (layer, brush, colour, samples so far; `live: false` when none). For painting along with the user; hosts stream the samples live. |
|
|
327
327
|
| `stroke_at` | Read the top-most stroke of a stroke layer that painted the pixel at `x`, `y`, or null. Use it to pick one stroke among overlapping ones. |
|
|
@@ -339,7 +339,7 @@ Listing, saving, sharing and previewing brushes are the brush library's tools (`
|
|
|
339
339
|
|
|
340
340
|
| Tool | Use |
|
|
341
341
|
| --- | --- |
|
|
342
|
-
| `get_wet_paint` | Read the wet paint: `wet`, the clock, `paused`, `speed`, `tilt`, the kernel (`backend`, `message` when it runs slower than it could), the GPU accelerator (`engine`) and each wet layer (`wetCells`, `wetBounds`, `activeTiles`, settings, flow map). Call after wet strokes. |
|
|
342
|
+
| `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. |
|
|
343
343
|
| `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`. |
|
|
344
344
|
| `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. |
|
|
345
345
|
| `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. |
|
|
@@ -462,7 +462,8 @@ The host may add the shared document tools (see `pixerate-agent-tools`). A paint
|
|
|
462
462
|
keep taking its colours.
|
|
463
463
|
- **Strokes take real time when the host shows your cursor.** With a director (the demo and
|
|
464
464
|
editors that set `createPaintEditorToolProvider({ director })`), `paint_stroke` paints live at
|
|
465
|
-
the pace of the points' `t` (else about 1.5 px per ms, at most ~1.8 s),
|
|
465
|
+
the pace of the points' `t` (else about 1.5 px per ms, at most ~1.8 s), `stroke_path` paints
|
|
466
|
+
each subpath in turn (paced by its `speed` when given) as one undo step, and `fill_layer` /
|
|
466
467
|
`replay_strokes` move the cursor first. Results and undo are the same; it is one more reason to
|
|
467
468
|
paint a few long strokes and replay them rather than many short ones. A stroke fails with "A
|
|
468
469
|
stroke is in progress" while the user is painting; try it again afterwards.
|
|
@@ -470,7 +471,10 @@ The host may add the shared document tools (see `pixerate-agent-tools`). A paint
|
|
|
470
471
|
flowed; `advance_wet_paint` first. Paint that should stay exactly where it was laid needs
|
|
471
472
|
`dry_paint` (or a dry medium).
|
|
472
473
|
- **Wet strokes on one layer interact**; washes that must not mix go on separate layers, or dry
|
|
473
|
-
the first before painting the second (glazing). At most 8 layers hold wet paint at once
|
|
474
|
+
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
|
|
475
|
+
that limit is lost (`dry_paint` frees tiles). Multi-threaded wet media needs a cross-origin isolated
|
|
476
|
+
page (COOP / COEP, for `SharedArrayBuffer`) and runs on one thread otherwise, more slowly but with
|
|
477
|
+
the same result.
|
|
474
478
|
- **Undoing far back** past the wet undo memory (512 MB by default) leaves that paint dry as it
|
|
475
479
|
looked, rather than wet.
|
|
476
480
|
- **Replays repeat what was recorded**: strokes, fills, clears, flattened relief and wet events.
|
|
@@ -28,6 +28,15 @@
|
|
|
28
28
|
dries it first (in the same undo step).
|
|
29
29
|
- **Time** runs by itself in an editor on screen (`pause_wet_paint` stops it); for an agent with
|
|
30
30
|
no screen, nothing moves until `advance_wet_paint` or `dry_paint`.
|
|
31
|
+
- **Extent limit (8 wet layers, 328 tiles).** The simulation holds at most 8 wet layers and 328
|
|
32
|
+
live tiles of 256 × 256 px across them (one wasm32 memory, under 4 GB). Water that spreads beyond
|
|
33
|
+
them is lost (`get_wet_paint` reports `activeTiles` per layer, so watch the total); dry
|
|
34
|
+
finished washes with `dry_paint` to free their tiles before painting another large wash.
|
|
35
|
+
- **Multi-threading and COOP / COEP.** Stepping wet tiles across Web Workers needs
|
|
36
|
+
`SharedArrayBuffer`, which browsers only expose on cross-origin isolated pages
|
|
37
|
+
(`Cross-Origin-Opener-Policy: same-origin` and `Cross-Origin-Embedder-Policy: require-corp` or
|
|
38
|
+
`credentialless`). Without cross-origin isolation the simulation runs on one thread, more slowly
|
|
39
|
+
but with identical results, and `get_wet_paint` says why in the kernel's `message`.
|
|
31
40
|
- **The GPU only draws.** With WebGPU and a large wet area (16 tiles of 256 px by default), Engine B
|
|
32
41
|
shades the wet paint on the GPU; the CPU engine still computes every step, so the painting,
|
|
33
42
|
`dry_paint`, saving, export and replay come out the same with it on or off. `get_wet_paint`
|