@pixerate/editor 0.252.0 → 0.253.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/brushes/index.cjs +229 -2014
- package/dist/brushes/index.d.cts +5 -1
- package/dist/brushes/index.d.ts +5 -1
- package/dist/brushes/index.js +236 -2021
- package/dist/brushes/patch.d.cts +23 -0
- package/dist/brushes/patch.d.ts +23 -0
- package/dist/brushes/ui.d.cts +105 -0
- package/dist/brushes/ui.d.ts +105 -0
- package/dist/chunk-34KLWUH4.cjs +2284 -0
- package/dist/chunk-QPHNVZHO.js +2284 -0
- package/dist/paint-editor/brush-controls.d.cts +57 -0
- package/dist/paint-editor/brush-controls.d.ts +57 -0
- package/dist/paint-editor/brush-library-tools.d.cts +15 -0
- package/dist/paint-editor/brush-library-tools.d.ts +15 -0
- package/dist/paint-editor/brush-library.d.cts +29 -0
- package/dist/paint-editor/brush-library.d.ts +29 -0
- package/dist/paint-editor/controller.d.cts +76 -17
- package/dist/paint-editor/controller.d.ts +76 -17
- package/dist/paint-editor/index.cjs +537 -852
- package/dist/paint-editor/index.d.cts +1 -0
- package/dist/paint-editor/index.d.ts +1 -0
- package/dist/paint-editor/index.js +327 -642
- package/dist/paint-editor/serialize.d.cts +7 -4
- package/dist/paint-editor/serialize.d.ts +7 -4
- package/dist/paint-editor/sticker-tools.d.cts +1 -1
- package/dist/paint-editor/sticker-tools.d.ts +1 -1
- package/dist/paint-editor/strokes.d.cts +10 -1
- package/dist/paint-editor/strokes.d.ts +10 -1
- package/dist/paint-editor/tools.d.cts +1 -1
- package/dist/paint-editor/tools.d.ts +1 -1
- package/dist/paint-editor/ui.d.cts +3 -51
- package/dist/paint-editor/ui.d.ts +3 -51
- package/dist/paint-editor/wet-tools.d.cts +1 -1
- package/dist/paint-editor/wet-tools.d.ts +1 -1
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +5 -3
- package/skills/pixerate-paint-editor/SKILL.md +26 -24
- package/skills/pixerate-paint-editor/references/brush-facets.md +30 -0
- package/skills/pixerate-paint-editor/references/gradient-paint.md +1 -1
- package/skills/pixerate-paint-editor/references/light-paint.md +2 -2
- package/skills/pixerate-paint-editor/references/oils.md +1 -1
- package/skills/pixerate-paint-editor/references/particle-brushes.md +8 -5
- package/skills/pixerate-paint-oil-impasto/SKILL.md +1 -1
- package/skills/pixerate-stickers/SKILL.md +1 -1
- package/skills/pixerate-video-editor/SKILL.md +1 -1
|
@@ -9,11 +9,14 @@
|
|
|
9
9
|
* as new assets keyed by layer id without breaking older readers (see `PaintDocumentExtensions`).
|
|
10
10
|
*/
|
|
11
11
|
import { type ImageEditorAssetStore, type SerializedLayer } from '../image-editor/layers/serialize.cjs';
|
|
12
|
-
import {
|
|
12
|
+
import { strokeToJSON } from './strokes.cjs';
|
|
13
13
|
import { type PaintDocumentState } from './document.cjs';
|
|
14
14
|
import { type PaperSettings } from './paper.cjs';
|
|
15
15
|
export declare const PAINT_FORMAT: "pixerate-paint";
|
|
16
|
-
|
|
16
|
+
/** 2: recorded strokes keep facet brushes (version 1 documents, with flat engine brushes, still load). */
|
|
17
|
+
export declare const PAINT_SCHEMA_VERSION: 2;
|
|
18
|
+
/** A recorded stroke as a document stores it (`strokeToJSON`). */
|
|
19
|
+
export type SerializedStroke = ReturnType<typeof strokeToJSON>;
|
|
17
20
|
/** Where a host keeps layer PNGs outside the JSON (the image editor's asset store contract). */
|
|
18
21
|
export type PaintAssetStore = ImageEditorAssetStore;
|
|
19
22
|
/**
|
|
@@ -34,8 +37,8 @@ export interface SerializedPaintDocument {
|
|
|
34
37
|
/** Asset id → PNG data URL (or an external reference). */
|
|
35
38
|
assets: Record<string, string>;
|
|
36
39
|
activeLayerId: string | null;
|
|
37
|
-
/** Recorded strokes (strokes are data), oldest first
|
|
38
|
-
strokes?:
|
|
40
|
+
/** Recorded strokes (strokes are data), oldest first, each brush a facet `Brush`; missing when saved without them. */
|
|
41
|
+
strokes?: SerializedStroke[];
|
|
39
42
|
/** Everything else (document-level state of later phases), written back as read. */
|
|
40
43
|
[extension: string]: unknown;
|
|
41
44
|
}
|
|
@@ -9,11 +9,14 @@
|
|
|
9
9
|
* as new assets keyed by layer id without breaking older readers (see `PaintDocumentExtensions`).
|
|
10
10
|
*/
|
|
11
11
|
import { type ImageEditorAssetStore, type SerializedLayer } from '../image-editor/layers/serialize.js';
|
|
12
|
-
import {
|
|
12
|
+
import { strokeToJSON } from './strokes.js';
|
|
13
13
|
import { type PaintDocumentState } from './document.js';
|
|
14
14
|
import { type PaperSettings } from './paper.js';
|
|
15
15
|
export declare const PAINT_FORMAT: "pixerate-paint";
|
|
16
|
-
|
|
16
|
+
/** 2: recorded strokes keep facet brushes (version 1 documents, with flat engine brushes, still load). */
|
|
17
|
+
export declare const PAINT_SCHEMA_VERSION: 2;
|
|
18
|
+
/** A recorded stroke as a document stores it (`strokeToJSON`). */
|
|
19
|
+
export type SerializedStroke = ReturnType<typeof strokeToJSON>;
|
|
17
20
|
/** Where a host keeps layer PNGs outside the JSON (the image editor's asset store contract). */
|
|
18
21
|
export type PaintAssetStore = ImageEditorAssetStore;
|
|
19
22
|
/**
|
|
@@ -34,8 +37,8 @@ export interface SerializedPaintDocument {
|
|
|
34
37
|
/** Asset id → PNG data URL (or an external reference). */
|
|
35
38
|
assets: Record<string, string>;
|
|
36
39
|
activeLayerId: string | null;
|
|
37
|
-
/** Recorded strokes (strokes are data), oldest first
|
|
38
|
-
strokes?:
|
|
40
|
+
/** Recorded strokes (strokes are data), oldest first, each brush a facet `Brush`; missing when saved without them. */
|
|
41
|
+
strokes?: SerializedStroke[];
|
|
39
42
|
/** Everything else (document-level state of later phases), written back as read. */
|
|
40
43
|
[extension: string]: unknown;
|
|
41
44
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent tools for stickers: stamps sprayed with a sticker brush (`paint_stroke`,
|
|
2
|
+
* Agent tools for stickers: stamps sprayed with a sticker brush (`paint_stroke`, list_brush_presets
|
|
3
3
|
* category sticker) stay objects on their layer, which these tools list, move, turn, resize,
|
|
4
4
|
* recolour, reorder and delete, find by point (`sticker_at`), and places new ones exactly (`add_stickers`). Each change is one undo step and redraws the layer.
|
|
5
5
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent tools for stickers: stamps sprayed with a sticker brush (`paint_stroke`,
|
|
2
|
+
* Agent tools for stickers: stamps sprayed with a sticker brush (`paint_stroke`, list_brush_presets
|
|
3
3
|
* category sticker) stay objects on their layer, which these tools list, move, turn, resize,
|
|
4
4
|
* recolour, reorder and delete, find by point (`sticker_at`), and places new ones exactly (`add_stickers`). Each change is one undo step and redraws the layer.
|
|
5
5
|
*/
|
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
* Strokes as data. Every committed stroke is recorded with the brush, colour, raw pen samples,
|
|
3
3
|
* jitter seed and symmetry copies it was painted with, so it replays to the same pixels, and can
|
|
4
4
|
* be replayed moved, scaled, rotated, recoloured or with another brush (`replay_strokes`).
|
|
5
|
+
*
|
|
6
|
+
* In memory a stroke keeps its brush as the engine painted it. Saved, the brush is a facet brush
|
|
7
|
+
* (`strokeToJSON`, documents of version 2); strokes saved with the flat engine brush (version 1)
|
|
8
|
+
* still read, and both replay to the same pixels.
|
|
5
9
|
*/
|
|
6
10
|
import { type PaintBrush } from './brushes.cjs';
|
|
11
|
+
import type { Brush } from '../brushes/types.cjs';
|
|
7
12
|
import type { PenPoint, StrokeCopy } from './engine.cjs';
|
|
8
13
|
import type { MixerLoad } from '../paint/exchange.cjs';
|
|
9
14
|
import { type Stencil } from './stencils.cjs';
|
|
@@ -46,7 +51,11 @@ export declare function invertAffine(m: Affine): Affine;
|
|
|
46
51
|
export declare function mapPenPoint(m: Affine, p: PenPoint): PenPoint;
|
|
47
52
|
/** An affine copy as the engine's `StrokeCopy`. */
|
|
48
53
|
export declare function affineCopy(m: Affine): StrokeCopy;
|
|
49
|
-
/** A recorded stroke
|
|
54
|
+
/** A recorded stroke as saved: plain JSON with its brush as a facet brush. */
|
|
55
|
+
export declare function strokeToJSON(stroke: RecordedStroke): Omit<RecordedStroke, 'brush'> & {
|
|
56
|
+
brush: Brush;
|
|
57
|
+
};
|
|
58
|
+
/** A recorded stroke read from JSON (its brush version 1 or 2), or `null` when it is not one. */
|
|
50
59
|
export declare function normalizeBrushStroke(raw: unknown): RecordedStroke | null;
|
|
51
60
|
/** The bounding box of a stroke's points. */
|
|
52
61
|
export declare function strokeBounds(points: readonly PenPoint[]): {
|
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
* Strokes as data. Every committed stroke is recorded with the brush, colour, raw pen samples,
|
|
3
3
|
* jitter seed and symmetry copies it was painted with, so it replays to the same pixels, and can
|
|
4
4
|
* be replayed moved, scaled, rotated, recoloured or with another brush (`replay_strokes`).
|
|
5
|
+
*
|
|
6
|
+
* In memory a stroke keeps its brush as the engine painted it. Saved, the brush is a facet brush
|
|
7
|
+
* (`strokeToJSON`, documents of version 2); strokes saved with the flat engine brush (version 1)
|
|
8
|
+
* still read, and both replay to the same pixels.
|
|
5
9
|
*/
|
|
6
10
|
import { type PaintBrush } from './brushes.js';
|
|
11
|
+
import type { Brush } from '../brushes/types.js';
|
|
7
12
|
import type { PenPoint, StrokeCopy } from './engine.js';
|
|
8
13
|
import type { MixerLoad } from '../paint/exchange.js';
|
|
9
14
|
import { type Stencil } from './stencils.js';
|
|
@@ -46,7 +51,11 @@ export declare function invertAffine(m: Affine): Affine;
|
|
|
46
51
|
export declare function mapPenPoint(m: Affine, p: PenPoint): PenPoint;
|
|
47
52
|
/** An affine copy as the engine's `StrokeCopy`. */
|
|
48
53
|
export declare function affineCopy(m: Affine): StrokeCopy;
|
|
49
|
-
/** A recorded stroke
|
|
54
|
+
/** A recorded stroke as saved: plain JSON with its brush as a facet brush. */
|
|
55
|
+
export declare function strokeToJSON(stroke: RecordedStroke): Omit<RecordedStroke, 'brush'> & {
|
|
56
|
+
brush: Brush;
|
|
57
|
+
};
|
|
58
|
+
/** A recorded stroke read from JSON (its brush version 1 or 2), or `null` when it is not one. */
|
|
50
59
|
export declare function normalizeBrushStroke(raw: unknown): RecordedStroke | null;
|
|
51
60
|
/** The bounding box of a stroke's points. */
|
|
52
61
|
export declare function strokeBounds(points: readonly PenPoint[]): {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent tools for the paint editor (`createPaintEditorToolProvider`). Strict schemas, every
|
|
3
3
|
* argument described, all four annotations. Each write is one undo step (or editor state, said so)
|
|
4
|
-
* and returns what it changed; ids come from the read tools (`list_layers`, `
|
|
4
|
+
* and returns what it changed; ids come from the read tools (`list_layers`, the brush library's `list_brush_presets`,
|
|
5
5
|
* `list_papers`, `list_strokes`).
|
|
6
6
|
*/
|
|
7
7
|
import type { AgentToolProvider } from '../tools/registry.cjs';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent tools for the paint editor (`createPaintEditorToolProvider`). Strict schemas, every
|
|
3
3
|
* argument described, all four annotations. Each write is one undo step (or editor state, said so)
|
|
4
|
-
* and returns what it changed; ids come from the read tools (`list_layers`, `
|
|
4
|
+
* and returns what it changed; ids come from the read tools (`list_layers`, the brush library's `list_brush_presets`,
|
|
5
5
|
* `list_papers`, `list_strokes`).
|
|
6
6
|
*/
|
|
7
7
|
import type { AgentToolProvider } from '../tools/registry.js';
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { MixerLoad } from '../paint/exchange.cjs';
|
|
12
12
|
import { type BlendModeInfo } from '../raster/blend.cjs';
|
|
13
|
-
import type { ImpastoTool,
|
|
13
|
+
import type { ImpastoTool, WetMediumKind, WetTool } from './brushes.cjs';
|
|
14
14
|
import type { PaintEditorController } from './controller.cjs';
|
|
15
15
|
import type { PenPoint } from './engine.cjs';
|
|
16
16
|
import { type Point2 } from './guides.cjs';
|
|
@@ -133,15 +133,8 @@ export declare function guideOverlay(controller: PaintEditorController, drag?: {
|
|
|
133
133
|
to: Point2;
|
|
134
134
|
kind: GuideOverlayKind;
|
|
135
135
|
}>;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
path: string;
|
|
139
|
-
label: string;
|
|
140
|
-
min: number;
|
|
141
|
-
max: number;
|
|
142
|
-
step: number;
|
|
143
|
-
}
|
|
144
|
-
export declare const BRUSH_SLIDERS: readonly SliderControl[];
|
|
136
|
+
export { BRUSH_SLIDERS, brushEngineControls, multiColorSliders, patchBrushValue, type BrushEngineControls, type SliderControl } from './brush-controls.cjs';
|
|
137
|
+
import type { SliderControl } from './brush-controls.cjs';
|
|
145
138
|
export declare const PAPER_SLIDERS: readonly SliderControl[];
|
|
146
139
|
/** Reads `a.b` from an object. */
|
|
147
140
|
export declare function readPath(obj: unknown, path: string): number;
|
|
@@ -174,47 +167,6 @@ export interface BlendMenuGroup {
|
|
|
174
167
|
*/
|
|
175
168
|
export declare const BLEND_MENU_GROUPS: readonly BlendMenuGroup[];
|
|
176
169
|
/** The engine-specific part of the brush panel: which sliders and toggles the active brush has. */
|
|
177
|
-
export interface BrushEngineControls {
|
|
178
|
-
/** Section heading. */
|
|
179
|
-
title: string;
|
|
180
|
-
sliders: readonly SliderControl[];
|
|
181
|
-
/** Where the RGB / pigment choice is stored, or `null` when the engine has none. */
|
|
182
|
-
mixingPath: 'behavior.mixing' | 'blender.mixing' | 'smudge.mixing' | null;
|
|
183
|
-
/** The dirty-brush toggle (`behavior.dirty`). */
|
|
184
|
-
dirty: boolean;
|
|
185
|
-
/** The multi-colour controls (`behavior.multicolor`; the panels show the brush gradient, `brush.paint`, instead). */
|
|
186
|
-
multicolor: boolean;
|
|
187
|
-
/** Load / Clean buttons and a swatch of what the brush carries. */
|
|
188
|
-
load: boolean;
|
|
189
|
-
/** The wet tool menu (`wet.tool`, `WET_TOOLS`) and medium menu (`wet.medium`, `WET_MEDIA`). */
|
|
190
|
-
wetTool?: boolean;
|
|
191
|
-
/** The impasto tool menu (`impasto.tool`, `IMPASTO_TOOLS`). */
|
|
192
|
-
impastoTool?: boolean;
|
|
193
|
-
/**
|
|
194
|
-
* The particle menus: kind and render (`particle.kind`, `particle.render`), ribbon pairs
|
|
195
|
-
* (`particle.ribbonPairs`), and the textured-dot stamps, order and rotation
|
|
196
|
-
* (`particle.dotTextures` up to `MAX_DOT_TEXTURES` of `STAMP_KINDS`, `dotTextureOrder`, `dotRotation`).
|
|
197
|
-
*/
|
|
198
|
-
particleMenus?: boolean;
|
|
199
|
-
/** The sticker picker for the brush's stickers (`sticker.stamps`, refs from the sticker library; `toggleStickerRef`). */
|
|
200
|
-
stickerStamps?: boolean;
|
|
201
|
-
/** Light paint: the "light follows pressure" toggle (`light.pressure`); the Light slider is in `sliders`. */
|
|
202
|
-
light?: boolean;
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* The controls the active brush's engine adds to the brush panel (`null` for the eraser):
|
|
206
|
-
* blender strength and blend distance; smudge strength and length; the Mixer Brush's pick-up,
|
|
207
|
-
* mix and load; a dab brush's pick-up and mix ratios. Every engine but the eraser has an RGB /
|
|
208
|
-
* pigment choice; dab and mixer brushes also have the dirty and multi-colour controls. Pick-up
|
|
209
|
-
* and mix always go through `behavior`, which keeps a Mixer Brush's `mixer` block in sync.
|
|
210
|
-
*/
|
|
211
|
-
export declare function brushEngineControls(brush: Pick<PaintBrush, 'engine'> & {
|
|
212
|
-
wet?: PaintBrush['wet'];
|
|
213
|
-
}): BrushEngineControls | null;
|
|
214
|
-
/** The multi-colour sliders for a mode: softness, and dabs per colour in `dab` mode. */
|
|
215
|
-
export declare function multiColorSliders(mode: string): readonly SliderControl[];
|
|
216
|
-
/** A brush change setting `path` (e.g. `smudge.mixing`, `behavior.dirty`) to any value, keeping the rest of its block. */
|
|
217
|
-
export declare function patchBrushValue(brush: PaintBrush, path: string, value: unknown): PaintBrushInput;
|
|
218
170
|
/** What the brush carries (picked-up paint, else loaded paint) as #rrggbb, or `null` when it is clean and empty. */
|
|
219
171
|
export declare function brushLoadColor(load: MixerLoad): string | null;
|
|
220
172
|
/** Sample sizes (square, in pad pixels) for picking from the mixing pad. */
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { MixerLoad } from '../paint/exchange.js';
|
|
12
12
|
import { type BlendModeInfo } from '../raster/blend.js';
|
|
13
|
-
import type { ImpastoTool,
|
|
13
|
+
import type { ImpastoTool, WetMediumKind, WetTool } from './brushes.js';
|
|
14
14
|
import type { PaintEditorController } from './controller.js';
|
|
15
15
|
import type { PenPoint } from './engine.js';
|
|
16
16
|
import { type Point2 } from './guides.js';
|
|
@@ -133,15 +133,8 @@ export declare function guideOverlay(controller: PaintEditorController, drag?: {
|
|
|
133
133
|
to: Point2;
|
|
134
134
|
kind: GuideOverlayKind;
|
|
135
135
|
}>;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
path: string;
|
|
139
|
-
label: string;
|
|
140
|
-
min: number;
|
|
141
|
-
max: number;
|
|
142
|
-
step: number;
|
|
143
|
-
}
|
|
144
|
-
export declare const BRUSH_SLIDERS: readonly SliderControl[];
|
|
136
|
+
export { BRUSH_SLIDERS, brushEngineControls, multiColorSliders, patchBrushValue, type BrushEngineControls, type SliderControl } from './brush-controls.js';
|
|
137
|
+
import type { SliderControl } from './brush-controls.js';
|
|
145
138
|
export declare const PAPER_SLIDERS: readonly SliderControl[];
|
|
146
139
|
/** Reads `a.b` from an object. */
|
|
147
140
|
export declare function readPath(obj: unknown, path: string): number;
|
|
@@ -174,47 +167,6 @@ export interface BlendMenuGroup {
|
|
|
174
167
|
*/
|
|
175
168
|
export declare const BLEND_MENU_GROUPS: readonly BlendMenuGroup[];
|
|
176
169
|
/** The engine-specific part of the brush panel: which sliders and toggles the active brush has. */
|
|
177
|
-
export interface BrushEngineControls {
|
|
178
|
-
/** Section heading. */
|
|
179
|
-
title: string;
|
|
180
|
-
sliders: readonly SliderControl[];
|
|
181
|
-
/** Where the RGB / pigment choice is stored, or `null` when the engine has none. */
|
|
182
|
-
mixingPath: 'behavior.mixing' | 'blender.mixing' | 'smudge.mixing' | null;
|
|
183
|
-
/** The dirty-brush toggle (`behavior.dirty`). */
|
|
184
|
-
dirty: boolean;
|
|
185
|
-
/** The multi-colour controls (`behavior.multicolor`; the panels show the brush gradient, `brush.paint`, instead). */
|
|
186
|
-
multicolor: boolean;
|
|
187
|
-
/** Load / Clean buttons and a swatch of what the brush carries. */
|
|
188
|
-
load: boolean;
|
|
189
|
-
/** The wet tool menu (`wet.tool`, `WET_TOOLS`) and medium menu (`wet.medium`, `WET_MEDIA`). */
|
|
190
|
-
wetTool?: boolean;
|
|
191
|
-
/** The impasto tool menu (`impasto.tool`, `IMPASTO_TOOLS`). */
|
|
192
|
-
impastoTool?: boolean;
|
|
193
|
-
/**
|
|
194
|
-
* The particle menus: kind and render (`particle.kind`, `particle.render`), ribbon pairs
|
|
195
|
-
* (`particle.ribbonPairs`), and the textured-dot stamps, order and rotation
|
|
196
|
-
* (`particle.dotTextures` up to `MAX_DOT_TEXTURES` of `STAMP_KINDS`, `dotTextureOrder`, `dotRotation`).
|
|
197
|
-
*/
|
|
198
|
-
particleMenus?: boolean;
|
|
199
|
-
/** The sticker picker for the brush's stickers (`sticker.stamps`, refs from the sticker library; `toggleStickerRef`). */
|
|
200
|
-
stickerStamps?: boolean;
|
|
201
|
-
/** Light paint: the "light follows pressure" toggle (`light.pressure`); the Light slider is in `sliders`. */
|
|
202
|
-
light?: boolean;
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* The controls the active brush's engine adds to the brush panel (`null` for the eraser):
|
|
206
|
-
* blender strength and blend distance; smudge strength and length; the Mixer Brush's pick-up,
|
|
207
|
-
* mix and load; a dab brush's pick-up and mix ratios. Every engine but the eraser has an RGB /
|
|
208
|
-
* pigment choice; dab and mixer brushes also have the dirty and multi-colour controls. Pick-up
|
|
209
|
-
* and mix always go through `behavior`, which keeps a Mixer Brush's `mixer` block in sync.
|
|
210
|
-
*/
|
|
211
|
-
export declare function brushEngineControls(brush: Pick<PaintBrush, 'engine'> & {
|
|
212
|
-
wet?: PaintBrush['wet'];
|
|
213
|
-
}): BrushEngineControls | null;
|
|
214
|
-
/** The multi-colour sliders for a mode: softness, and dabs per colour in `dab` mode. */
|
|
215
|
-
export declare function multiColorSliders(mode: string): readonly SliderControl[];
|
|
216
|
-
/** A brush change setting `path` (e.g. `smudge.mixing`, `behavior.dirty`) to any value, keeping the rest of its block. */
|
|
217
|
-
export declare function patchBrushValue(brush: PaintBrush, path: string, value: unknown): PaintBrushInput;
|
|
218
170
|
/** What the brush carries (picked-up paint, else loaded paint) as #rrggbb, or `null` when it is clean and empty. */
|
|
219
171
|
export declare function brushLoadColor(load: MixerLoad): string | null;
|
|
220
172
|
/** Sample sizes (square, in pad pixels) for picking from the mixing pad. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent tools for wet media (watercolour and gouache on a simulated wet layer). Wet strokes are
|
|
3
|
-
* painted with `paint_stroke` and a wet brush (`
|
|
3
|
+
* painted with `paint_stroke` and a wet brush (`list_brush_presets` variety `watercolor` or
|
|
4
4
|
* `wet-tool`); these tools read and steer the wet paint. Every result says whether paint is still
|
|
5
5
|
* wet. Settings (wet parameters, flow maps, tilt) are saved with the document but are not undo
|
|
6
6
|
* steps; drying and wetting the paper are.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent tools for wet media (watercolour and gouache on a simulated wet layer). Wet strokes are
|
|
3
|
-
* painted with `paint_stroke` and a wet brush (`
|
|
3
|
+
* painted with `paint_stroke` and a wet brush (`list_brush_presets` variety `watercolor` or
|
|
4
4
|
* `wet-tool`); these tools read and steer the wet paint. Every result says whether paint is still
|
|
5
5
|
* wet. Settings (wet parameters, flow maps, tilt) are saved with the document but are not undo
|
|
6
6
|
* steps; drying and wetting the paper are.
|
package/package.json
CHANGED
|
@@ -80,8 +80,10 @@ paints without (warnings), each with a fix; lists and writes use the current hos
|
|
|
80
80
|
marks take any sticker ref from `find_stickers`.
|
|
81
81
|
- **Out-of-range values** are refused by the schema (`tip.size` is 1..2500 px); a stored brush
|
|
82
82
|
is clamped on import and reported in `problems`.
|
|
83
|
-
- **The paint editor
|
|
84
|
-
|
|
83
|
+
- **The paint editor paints from this library.** Its `set_brush` picks a brush by id here and
|
|
84
|
+
lays facets over it without saving; `create_brush` / `update_brush` store one. A paint host
|
|
85
|
+
registers these tools with its own preview (`createPaintBrushLibraryToolProvider`), so the
|
|
86
|
+
paint editor has no list, save, export, import or thumbnail tools of its own.
|
|
85
87
|
|
|
86
88
|
## Workflow skills
|
|
87
89
|
|
|
@@ -94,7 +96,7 @@ paints without (warnings), each with a fix; lists and writes use the current hos
|
|
|
94
96
|
| --- | --- |
|
|
95
97
|
| `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
98
|
| `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`. |
|
|
99
|
+
| `create_brush` | Save a new brush: `id`, `name`, optional `basedOn`, and the facets (to keep an editor's current brush, pass the `brush` its `get_brush` returns). Normalised and checked for this host; refused brushes save nothing. Returns `id`, `brush`, `engine`, `problems`, `warnings`. |
|
|
98
100
|
| `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
101
|
| `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
102
|
| `remove_brush` | Delete a saved brush for good (export it first to keep a copy). Built-ins are refused. Returns `removed`. |
|
|
@@ -11,25 +11,27 @@ seed: its grain is a height map (peaks and valleys) that grain-responsive brushe
|
|
|
11
11
|
is never part of a layer. Coordinates are document pixels, (0, 0) top-left, y down. See
|
|
12
12
|
`pixerate-agent-tools` for errors, namespacing and batching.
|
|
13
13
|
|
|
14
|
-
- **Brushes**
|
|
15
|
-
|
|
16
|
-
(pressure, tilt, velocity, jitter
|
|
17
|
-
|
|
14
|
+
- **Brushes** come from the shared brush library (`pixerate-brushes`: `list_brush_presets`,
|
|
15
|
+
`create_brush`, `preview_brush`…) and are made of facets: a tip (size, hardness, spacing, angle,
|
|
16
|
+
roundness, opacity, flow, blend), dynamics (pressure, tilt, velocity, jitter, a **rotation**
|
|
17
|
+
mode `fixed`, `stroke` or `barrel`), behaviour (paper **grain** response, pick-up, wet or thick
|
|
18
|
+
surface), marks, light, motion and colour. `set_brush` chooses one and lays facet changes over
|
|
19
|
+
it; `get_brush` reads it with the engine it paints with: `dab` (most media), `eraser`, `mixer` (the Mixer Brush: a reservoir of paint plus paint
|
|
18
20
|
it picks up), `blender` (mixes the colours under and near the tip) or `smudge` (drags paint
|
|
19
21
|
along the stroke), `wet` (watercolour, gouache, oil and the wet tools, below), `impasto`
|
|
20
22
|
(thick paint with relief and material, below), `particle` (procedural particle brushes),
|
|
21
23
|
`bristle` (a tuft of bristles) or `sticker` (sprays editable stickers).
|
|
22
|
-
- **Wet media** (
|
|
24
|
+
- **Wet media** (engine `wet`: `behaviour.surface` `wet`, and the wet tools; categories `watercolor` and `wet-tool`): a stroke lays water
|
|
23
25
|
and pigment on the layer's **wet layer**, a fluid simulation that keeps running after the
|
|
24
26
|
stroke: the water spreads until its edge is pinned by the paper, carries pigment out to the
|
|
25
27
|
rim as it dries (edge darkening), drops pigment into the paper's valleys (granulation), pushes
|
|
26
28
|
pigment back where new water flows in (blooms), bleeds between touching wet colours and runs
|
|
27
29
|
downhill on a tilted canvas. Paint stays wet until it dries by itself (a few thousand steps)
|
|
28
30
|
or `dry_paint` dries it; a dried wash is fixed, so the next wash **glazes** over it. A wet
|
|
29
|
-
brush
|
|
30
|
-
`pigment` (concentration), `body` (0 transparent watercolour .. 1
|
|
31
|
-
and `rewet` set it up. Every result says whether paint is still wet (`wet` / `stillWet`).
|
|
32
|
-
- **Behaviour** (`
|
|
31
|
+
brush paints, or is a tool (`tool` `water`, `dryer`, `blow`, `blot`, `wet-blend`, `wet-drag`);
|
|
32
|
+
`behaviour.wet` `water`, `pigment` (concentration), `body` (0 transparent watercolour .. 1
|
|
33
|
+
opaque gouache) and `rewet`, and `behaviour.strength`, set it up. Every result says whether paint is still wet (`wet` / `stillWet`).
|
|
34
|
+
- **Behaviour** (`behaviour.exchange`, dab and mixer brushes) is how a brush treats paint already on the
|
|
33
35
|
canvas: a **pick-up ratio** (how much paint each dab lifts and carries), a **mix ratio** (how
|
|
34
36
|
much of the carried paint goes into what it lays down), **dirty** (keep the carried colour into
|
|
35
37
|
the next stroke) and **multi-colour** (`tip`: several colours side by side across the tip;
|
|
@@ -147,8 +149,12 @@ the pitfalls, and uses the tools below.
|
|
|
147
149
|
painted moves relative to anything else). Adding `left` or `top` shifts every coordinate you
|
|
148
150
|
hold by (+left, +top): re-read `list_layers` or use the returned `rect`. Dry wet paint first.
|
|
149
151
|
`set_canvas` only crops or grows at the bottom-right.
|
|
150
|
-
- **Save brushes you build**
|
|
151
|
-
`
|
|
152
|
+
- **Save brushes you build** in the brush library: `create_brush` with `basedOn` and the facets
|
|
153
|
+
you changed (or `get_brush` then `create_brush` with its `brush`), and share them with
|
|
154
|
+
`export_brushes` / `import_brushes`. A saved brush shows in every editor that shares the
|
|
155
|
+
library; `set_brush` its id to paint with it.
|
|
156
|
+
|
|
157
|
+
Which facet sets which engine setting: [references/brush-facets.md](references/brush-facets.md).
|
|
152
158
|
|
|
153
159
|
## Wet media
|
|
154
160
|
|
|
@@ -178,12 +184,12 @@ inner glow, shadows, stroke, bevel, satin and overlays, as in the image editor
|
|
|
178
184
|
|
|
179
185
|
- **Particle brushes** (category `procedural`; ribbons, flames and bokeh are in `light`):
|
|
180
186
|
`hair-strands`, `spring-ink`, `orbit-curls`, `flow-fur`, `sparkle-dust`, `bead-trail`. Tune
|
|
181
|
-
with `
|
|
182
|
-
sequence, ribbon), waves and textured dots; read [references/particle-brushes.md](references/particle-brushes.md).
|
|
187
|
+
with `marks` (kind `particles`): physics (string, spring, orbit, flow, elastic, fuzzy), render
|
|
188
|
+
(dot, line, sequence, ribbon), waves and textured dots (`tip.stamps`); read [references/particle-brushes.md](references/particle-brushes.md).
|
|
183
189
|
Draw slowly and with varying direction: the particles react to movement.
|
|
184
190
|
- **Bristle brushes** (category `bristle`): `bristle-round`, `bristle-flat`, `dry-brush`. Every
|
|
185
191
|
bristle draws its own line: press harder to splay the tuft, tilt to flatten it; soft bristles
|
|
186
|
-
bend into curves at turns; a low `bristle.load` runs dry into broken streaks.
|
|
192
|
+
bend into curves at turns; a low `tip.bristle.load` runs dry into broken streaks.
|
|
187
193
|
- **Sticker spray** (category `sticker`): stickers by ref (`editor:star`, `editor:leaf`… or any
|
|
188
194
|
from the host's library: `find_stickers`; tintable ones take the paint colour) sprayed onto an
|
|
189
195
|
**empty layer**, each staying an object:
|
|
@@ -289,16 +295,12 @@ is a canvas coordinate: read [references/canvas-hosted.md](references/canvas-hos
|
|
|
289
295
|
|
|
290
296
|
### Brushes
|
|
291
297
|
|
|
298
|
+
Listing, saving, sharing and previewing brushes are the brush library's tools (`pixerate-brushes`), registered by the host next to these.
|
|
299
|
+
|
|
292
300
|
| Tool | Use |
|
|
293
301
|
| --- | --- |
|
|
294
|
-
| `
|
|
295
|
-
| `
|
|
296
|
-
| `set_brush` | Choose the active brush (`id`) and / or change it: `tip` (size px, hardness, spacing, angle, roundness, opacity, flow, smoothing, pressureSize, pressureOpacity, blend), `grain`, `pressureSmoothing`, `rotation`, `dynamics` (minSize, pressureFlow, tiltSize, tiltRoundness, tiltOpacity, velocitySize, velocityOpacity, jitters, scatter), `engine`, `mixer`, `loadsColor`, `behavior` (pickup, mix, dirty, mixing; multicolor is the older form of `paint`), `paint` (the brush's own gradient, or null for the editor's paint), `blender` (strength, distance, mixing), `smudge` (strength, length, mixing). Editor state. Returns the brush. |
|
|
297
|
-
| `save_brush` | Store the active brush in the user library under `id` (lowercase, digits, dashes) and `name`. Built-in ids are refused. |
|
|
298
|
-
| `remove_brush` | Delete a user brush. Built-in brushes cannot be removed. |
|
|
299
|
-
| `export_brushes` | Get a brush library file (JSON) of `ids`, or of every user brush. |
|
|
300
|
-
| `import_brushes` | Add the brushes of a library file to the user library; taken ids are skipped unless `replace`. Returns `added`, `skipped`, `problems`. |
|
|
301
|
-
| `render_brush_thumbnail` | See what a brush does: a PNG of a test stroke (S-curve, pressure swelling and fading) on the current paper. Cheaper than painting and undoing. |
|
|
302
|
+
| `get_brush` | Read a brush as facets (`brush`), or the active brush as edited (no `id`), with the `engine` and `category` it paints with, `builtin` (an unchanged preset) and `strokePaint` (what its next stroke paints). Read before changing a brush you did not build. |
|
|
303
|
+
| `set_brush` | Choose the active brush (`id`, from `list_brush_presets`) and / or lay facets over it: `tip`, `marks`, `dynamics`, `behaviour`, `light`, `motion`, `colour` (objects merge, lists replace; marks of another kind replace the marks), `unset` facets to drop. Editor state, not saved: `create_brush` stores a brush. Returns `brush` (facets), `engine` and `problems` (values clamped). The old flat fields (`particle`, `impasto`, `behavior`…) are refused. |
|
|
302
304
|
|
|
303
305
|
### Colour
|
|
304
306
|
|
|
@@ -329,10 +331,10 @@ is a canvas coordinate: read [references/canvas-hosted.md](references/canvas-hos
|
|
|
329
331
|
|
|
330
332
|
| Tool | Use |
|
|
331
333
|
| --- | --- |
|
|
332
|
-
| `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` changes, `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. |
|
|
334
|
+
| `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. |
|
|
333
335
|
| `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. |
|
|
334
336
|
| `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. |
|
|
335
|
-
| `update_stroke` | Change a stroke on a stroke layer: `brushId` (keeps its size), `brush`
|
|
337
|
+
| `update_stroke` | Change a stroke on a stroke layer: `brushId` (keeps its size), `brush` facets (as `set_brush` takes), `color`, `paint` (null drops a gradient), `seed`. Redraws exactly. One undo step. Returns the stroke and the changed `bounds`. |
|
|
336
338
|
| `edit_stroke_points` | Replace a stroke's `points`, or `transform` it (`dx`, `dy`, `scale`, `rotate`, `flipX`, about its centre or `origin`). One undo step. Returns the stroke with its points and the changed `bounds`. |
|
|
337
339
|
| `reorder_stroke` | Move a stroke to `index` in its stroke layer (0 = bottom). One undo step. Returns the order. |
|
|
338
340
|
| `remove_strokes` | Delete strokes from stroke layers (their eraser). One undo step. Returns the ids and `bounds`. |
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Brush facets in the paint editor
|
|
2
|
+
|
|
3
|
+
`set_brush`, `paint_stroke` `brush` and `update_stroke` `brush` take the brush library's facets
|
|
4
|
+
(see `pixerate-brushes`). `get_brush` returns a brush as facets plus the `engine` it paints with.
|
|
5
|
+
The engine's flat settings (`particle`, `impasto`, `behavior`, `paint`…) are not arguments any
|
|
6
|
+
more; this is where each one went.
|
|
7
|
+
|
|
8
|
+
| Engine setting | Facet |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| Tip size, hardness, spacing, angle, roundness, opacity, flow, blend | `tip` |
|
|
11
|
+
| Smoothing, pressure, tilt, velocity, jitter, scatter, rotation | `dynamics` |
|
|
12
|
+
| Grain, pick-up and mix (behavior), blender and smudge strength | `behaviour` (`grain`, `exchange`, `strength`, `distance`, `length`, `mixing`) |
|
|
13
|
+
| Mixer Brush reservoir | `behaviour.exchange.reservoir` (`load`, `refill`, `loadsColour`) |
|
|
14
|
+
| Wet engine (medium, water, pigment, body…) | `behaviour.surface` `wet` and `behaviour.wet` |
|
|
15
|
+
| Impasto (thickness, gloss, metallic, rim, clarity…) | `behaviour.surface` `thick` and `behaviour.thick` |
|
|
16
|
+
| Particle settings | `marks` `{ kind: 'particles', physics, render, count… }`; textured dots are `tip.stamps` on a `stamp` tip |
|
|
17
|
+
| Sticker spray | `marks` `{ kind: 'objects', density… }` and `tip.stamps` (sticker refs) |
|
|
18
|
+
| Bristles | `tip.shape` `bristle` and `tip.bristle` |
|
|
19
|
+
| A brush's own gradient (paint) | `colour.default` (a gradient); `unset: ['colour']` drops it |
|
|
20
|
+
| Light | `light` (`amount`, `pressure`) |
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
- A softer, bigger airbrush for one stroke: `paint_stroke` `{ brushId: "airbrush", brush: { tip:
|
|
25
|
+
{ size: 80, hardness: 0 } }, points }`.
|
|
26
|
+
- A dirty round that picks up more: `set_brush` `{ id: "dirty-round", behaviour: { exchange: {
|
|
27
|
+
pickup: 0.5, mix: 0.6 } } }`.
|
|
28
|
+
- Elastic ribbons with star dots: `set_brush` `{ id: "spring-ink", tip: { shape: "stamp", stamps:
|
|
29
|
+
["editor:star"] }, marks: { kind: "particles", physics: "elastic", render: "ribbon" } }`.
|
|
30
|
+
- A brush's own gradient off again: `set_brush` `{ unset: ["colour"] }`.
|
|
@@ -4,7 +4,7 @@ Paint that changes colour as the stroke goes: give a gradient where a colour wou
|
|
|
4
4
|
|
|
5
5
|
1. **`set_paint`** with `{ type: "gradient", stops, map }` makes it the paint for every following
|
|
6
6
|
stroke (`set_color` goes back to one colour); `paint_stroke` `paint` overrides it for one stroke;
|
|
7
|
-
a brush can carry its own (`set_brush` `
|
|
7
|
+
a brush can carry its own (`set_brush` `colour.default`, presets `gradient-round`, `pressure-ombre`,
|
|
8
8
|
`rainbow-marker`, `gradient-wash`).
|
|
9
9
|
2. **Choose the mapping by what the stroke should do**: `distance` (default, 300 px then
|
|
10
10
|
`mirror` back) for "drag it out" colour; `pressure` for light-to-heavy shading in one stroke;
|
|
@@ -18,8 +18,8 @@ particle ones are tuned in [particle-brushes.md](particle-brushes.md)).
|
|
|
18
18
|
`strength` 0..2 (default 1). It is not an undo step and repaints nothing; it shows the
|
|
19
19
|
painting as committed, so a stroke's spill appears when the stroke ends. It spills onto
|
|
20
20
|
everything below, paper included, so it reads best on dark paper (`set_paper` colour).
|
|
21
|
-
- **Glassy beads** (impasto): `impasto.rim` makes a bead's light stronger at its edges, where its
|
|
22
|
-
surface turns away (backlit glass); `
|
|
21
|
+
- **Glassy beads** (impasto): `behaviour.thick.rim` (engine `impasto.rim`) makes a bead's light stronger at its edges, where its
|
|
22
|
+
surface turns away (backlit glass); `behaviour.thick.clarity` lets the middle of a bead show the layers
|
|
23
23
|
below while its edges stay solid. `glow-gel` uses both: paint loops with a distance-mapped
|
|
24
24
|
gradient (`set_paint`) for glowing glass tubes.
|
|
25
25
|
- **Crossings.** Beads on one layer fuse where they cross (their heights combine by maximum), so
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
(azimuth, elevation, relief). Tools: `impasto-brush` (bristle ridges), `paint-tube` (blobs),
|
|
12
12
|
`palette-knife` (scrapes the relief flat and smears the paint), `paint-roller` (flat stippled
|
|
13
13
|
band), `gloop-pen` (glossy bead), `metallic-paint` (highlights in the paint's colour).
|
|
14
|
-
- **Loading and thinner**: `wet.load` / `
|
|
14
|
+
- **Loading and thinner**: `behaviour.wet.load` / `behaviour.thick.load` below 1 make the brush run out along a
|
|
15
15
|
long stroke (dry-brush ends); `thinner` makes paint flatter and more transparent.
|
|
16
16
|
- **Light** is a view of the relief, not paint: move it (`set_lighting`) to read the texture
|
|
17
17
|
(a low elevation, 15..30°, shows brushwork best) and pick the final light before exporting.
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Particle brushes
|
|
2
2
|
|
|
3
|
-
Particle brushes (`engine
|
|
3
|
+
Particle brushes (`marks` kind `particles`; engine `particle`) make marks with a small simulation driven by the pen. They
|
|
4
4
|
are seeded and stepped by distance, so the same points and `seed` paint the same pixels and
|
|
5
5
|
replays are exact. Their marks are ordinary coverage: opacity, blend modes, locks, stencils,
|
|
6
6
|
symmetry, gradient paint, effect paint and light paint all work as for a dab brush. Change them
|
|
7
|
-
with `set_brush` `
|
|
7
|
+
with `set_brush` `marks` `{ kind: 'particles', … }` (missing fields keep their values; the
|
|
8
|
+
engine's `particle.kind` is `marks.physics`, its textured dots `tip.stamps` on a `stamp` tip,
|
|
9
|
+
`dotTextureOrder` / `dotRotation` are `marks.stampOrder` / `marks.stampRotation`, `waveSpeed` is
|
|
10
|
+
`motion.waveSpeed`); `get_brush` returns them all.
|
|
8
11
|
|
|
9
|
-
## Kinds (`
|
|
12
|
+
## Kinds (`marks.physics`)
|
|
10
13
|
|
|
11
14
|
| Kind | Motion | Good for |
|
|
12
15
|
| --- | --- | --- |
|
|
@@ -21,7 +24,7 @@ with `set_brush` `particle` (missing fields keep their values); `get_brush` retu
|
|
|
21
24
|
`elastic` and `fuzzy` damp their strands enough to stay together at any setting; a `string` with
|
|
22
25
|
low damping and high stiffness can still swing wildly, which is part of its look.
|
|
23
26
|
|
|
24
|
-
## Renders (`
|
|
27
|
+
## Renders (`marks.render`)
|
|
25
28
|
|
|
26
29
|
- `dot`: a mark at every step; `line`: each particle's path as a line; `sequence`: beads spaced
|
|
27
30
|
by `interval` along each path.
|
|
@@ -59,7 +62,7 @@ light paint; see [light-paint.md](light-paint.md) for spill and the light-painti
|
|
|
59
62
|
|
|
60
63
|
## Best practice
|
|
61
64
|
|
|
62
|
-
- Check a setting with `
|
|
65
|
+
- Check a setting with `preview_brush` (the brush library) before painting with it.
|
|
63
66
|
- Change one thing at a time: kind for the motion, render for the look, then waves and textures.
|
|
64
67
|
- Many `flow` particles with long `life` in a `ribbon` are slow (every pair of live particles is
|
|
65
68
|
a band each step): keep `count` × `life` low (count 3..6, life ≤ 0.4).
|
|
@@ -67,7 +67,7 @@ This skill is the method. `pixerate-paint-editor` has the full tool reference an
|
|
|
67
67
|
| Blobs of paint straight from the tube | `paint-tube` |
|
|
68
68
|
| A glossy bead or line | `gloop-pen` |
|
|
69
69
|
| A glowing, glassy bead (a neon or glass tube) | `glow-gel` (light paint with rim and clarity, on dark paper; one loop per layer where they cross) |
|
|
70
|
-
| Dry, broken strokes over texture | `dry-brush`, or a lower `
|
|
70
|
+
| Dry, broken strokes over texture | `dry-brush`, or a lower `behaviour.thick.load` |
|
|
71
71
|
| A metallic highlight | `metallic-paint` |
|
|
72
72
|
| Paint that stays exactly as laid | `set_instant_dry` on |
|
|
73
73
|
|
|
@@ -19,7 +19,7 @@ none, it is the editor's own stamps (`editorStickers()`: `editor:dot`, `editor:s
|
|
|
19
19
|
2. **Check.** `describe_sticker` when the choice matters: its licence (and the attribution line
|
|
20
20
|
it asks for), dominant colours, variants and outline.
|
|
21
21
|
3. **Use.** Pass refs to the editor that places them: in the paint editor, a sticker brush
|
|
22
|
-
(`set_brush` `
|
|
22
|
+
(`set_brush` `tip.stamps`, then `paint_stroke`) sprays them and `add_stickers` places
|
|
23
23
|
them exactly. In the vector, image and canvas editors, `insert_sticker` puts one in (`x`,
|
|
24
24
|
`y` centre, `width`): vector, a group of editable paths; image, a pixel layer; canvas, a
|
|
25
25
|
shape node from its outline in one colour. A provider's art loads before it is drawn.
|
|
@@ -300,7 +300,7 @@ and every write tool is refused with the reason.
|
|
|
300
300
|
|
|
301
301
|
| Tool | Use it to |
|
|
302
302
|
| --- | --- |
|
|
303
|
-
| `search_effects` | Find effects: words in `query`, filtered by `kind`, `category`, `use` (filter, overlay for clips; transition; generator, title) or `accepts: ["path"]` (effects that draw along a path you give). Returns ids, names, uses, whether they are transparent or loop, and their length. Camera moves (`kind` camera) are listed but go on clips with `set_clip_camera_move`, not `apply_effect`. Call `describe_effect` next. |
|
|
303
|
+
| `search_effects` | Find effects: words in `query`, filtered by `kind`, `category`, `use` (filter, overlay for clips; transition; generator, title) or `accepts: ["path"]` (effects that draw along a path you give). Returns ids, names, uses, whether they are transparent or loop, and their length. Camera moves (`kind` camera) are listed but go on clips with `set_clip_camera_move`, not `apply_effect`. Timing effects (`kind` timing: speed changes, reverses, freezes, echoes) are listed but cannot be applied to clips yet (`appliesHere` false). Call `describe_effect` next. |
|
|
304
304
|
| `describe_effect` | Read one effect's `controls` (a strict JSON Schema: names, types, ranges, units), `defaults`, `presets` and `inputs`, and whether it `appliesHere` (as a clip effect). Use the names and ranges for values. |
|
|
305
305
|
| `list_applied_effects` | See the effects in the project per clip, in order: clip effects (`fx1`...), an effect clip's own effect (`generator`) and an effect transition (`transition`), with their saved values and `available` (false when the provider lacks it: drawn as a placeholder). |
|
|
306
306
|
| `apply_effect` | Add a filter or overlay effect to a clip's stack (`target` clip id, `effect`, `values`, `index`, `enabled`, `opacity`). Effects run in order on the clip's picture before its grade and placement. Returns the effect's new id and the clip's effects. |
|