@pixerate/editor 0.276.0 → 0.278.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/animation-editor/index.cjs +59 -59
- package/dist/animation-editor/index.js +3 -3
- package/dist/brushes/index.cjs +69 -67
- package/dist/brushes/index.js +6 -4
- package/dist/brushes/patch.d.cts +4 -4
- package/dist/brushes/patch.d.ts +4 -4
- package/dist/brushes/profiles.d.cts +2 -0
- package/dist/brushes/profiles.d.ts +2 -0
- package/dist/brushes/schema.d.cts +1 -0
- package/dist/brushes/schema.d.ts +1 -0
- package/dist/brushes/types.d.cts +10 -0
- package/dist/brushes/types.d.ts +10 -0
- package/dist/{brushstrokeRender-I6MYFCOU.cjs → brushstrokeRender-7HOMKZNO.cjs} +15 -15
- package/dist/{brushstrokeRender-FK3ASUUJ.js → brushstrokeRender-EIK3625T.js} +3 -3
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-U26LUXCJ.cjs → chunk-4NZTK7LM.cjs} +35 -35
- package/dist/{chunk-CVBTJVRN.js → chunk-DWPFGWW5.js} +1 -1
- package/dist/{chunk-XMSH66VU.js → chunk-FNIWHSLI.js} +1 -1
- package/dist/{chunk-QNNZA3V5.cjs → chunk-H3EME3S5.cjs} +2 -2
- package/dist/{chunk-4EM5NGCL.js → chunk-HHX7ST6Z.js} +1 -1
- package/dist/{chunk-Q33V5PEF.cjs → chunk-HRUK5TFW.cjs} +73 -12
- package/dist/{chunk-5HR5CSLC.cjs → chunk-JVFGK3DK.cjs} +69 -58
- package/dist/{chunk-JNMNM3SL.js → chunk-LZE2QZCT.js} +1 -1
- package/dist/{chunk-OS6OG7DN.js → chunk-N4MCWQZ7.js} +1 -1
- package/dist/{chunk-IJ6NSWKM.js → chunk-NJLPW4MM.js} +17 -6
- package/dist/{chunk-OY24XRYF.cjs → chunk-PEQWARCP.cjs} +12 -12
- package/dist/{chunk-XVPQNX7O.js → chunk-PPDUCZZV.js} +66 -5
- package/dist/{chunk-X7XBEX3O.cjs → chunk-QBZEC2JJ.cjs} +86 -86
- package/dist/{chunk-GHYJAMMS.js → chunk-ROURHJYT.js} +1 -1
- package/dist/{chunk-ZIE6EJGR.cjs → chunk-VNF7A2JA.cjs} +23 -23
- package/dist/{chunk-ISCAJBPQ.cjs → chunk-WFSYZO5Z.cjs} +1 -1
- package/dist/image-editor/index.cjs +788 -788
- package/dist/image-editor/index.js +4 -4
- package/dist/paint-editor/brush-model.d.cts +15 -1
- package/dist/paint-editor/brush-model.d.ts +15 -1
- package/dist/paint-editor/controller.d.cts +90 -9
- package/dist/paint-editor/controller.d.ts +90 -9
- package/dist/paint-editor/document.d.cts +8 -1
- package/dist/paint-editor/document.d.ts +8 -1
- package/dist/paint-editor/ferro-tools.d.cts +10 -0
- package/dist/paint-editor/ferro-tools.d.ts +10 -0
- package/dist/paint-editor/ferro.d.cts +134 -0
- package/dist/paint-editor/ferro.d.ts +134 -0
- package/dist/paint-editor/index.cjs +2138 -872
- package/dist/paint-editor/index.d.cts +2 -0
- package/dist/paint-editor/index.d.ts +2 -0
- package/dist/paint-editor/index.js +1446 -180
- package/dist/paint-editor/serialize.d.cts +3 -1
- package/dist/paint-editor/serialize.d.ts +3 -1
- package/dist/paint-editor/stroke.d.cts +17 -0
- package/dist/paint-editor/stroke.d.ts +17 -0
- package/dist/paint-editor/strokes.d.cts +11 -1
- package/dist/paint-editor/strokes.d.ts +11 -1
- package/dist/paint-editor/thick.d.cts +15 -2
- package/dist/paint-editor/thick.d.ts +15 -2
- package/dist/paint-editor/ui.d.cts +2 -0
- package/dist/paint-editor/ui.d.ts +2 -0
- package/dist/vector/index.cjs +998 -998
- package/dist/vector/index.js +4 -4
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +1 -0
- package/skills/pixerate-paint-editor/SKILL.md +12 -30
- package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
- package/skills/pixerate-paint-editor/references/ferrofluid.md +36 -0
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
parseOpenTypeFont,
|
|
9
9
|
removeAnchorsKeepingShape,
|
|
10
10
|
traceField
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-N4MCWQZ7.js";
|
|
12
12
|
import {
|
|
13
13
|
ADJUSTMENT_KEYS,
|
|
14
14
|
ADJUSTMENT_KINDS,
|
|
@@ -409,7 +409,7 @@ import {
|
|
|
409
409
|
writePsd,
|
|
410
410
|
xyToTempTint,
|
|
411
411
|
xyToUv
|
|
412
|
-
} from "../chunk-
|
|
412
|
+
} from "../chunk-FNIWHSLI.js";
|
|
413
413
|
import {
|
|
414
414
|
flattenPath,
|
|
415
415
|
rasterizeCoverage
|
|
@@ -683,14 +683,14 @@ import {
|
|
|
683
683
|
warpMeshParamAt,
|
|
684
684
|
warpMeshRows,
|
|
685
685
|
warpPresetMesh
|
|
686
|
-
} from "../chunk-
|
|
686
|
+
} from "../chunk-HHX7ST6Z.js";
|
|
687
687
|
import {
|
|
688
688
|
IMAGE_PROFILE,
|
|
689
689
|
checkBrush,
|
|
690
690
|
closest,
|
|
691
691
|
createBrushLibrary,
|
|
692
692
|
resolveBrush
|
|
693
|
-
} from "../chunk-
|
|
693
|
+
} from "../chunk-PPDUCZZV.js";
|
|
694
694
|
import "../chunk-JL6YH5WD.js";
|
|
695
695
|
import "../chunk-RWDSSK2I.js";
|
|
696
696
|
import {
|
|
@@ -149,6 +149,17 @@ export interface MutationSettings {
|
|
|
149
149
|
}
|
|
150
150
|
export declare const DEFAULT_MUTATION: Readonly<MutationSettings>;
|
|
151
151
|
export declare function normalizeMutation(raw?: Partial<MutationSettings>, base?: MutationSettings): MutationSettings;
|
|
152
|
+
/** Ferrofluid paint: how much liquid ferrofluid a brush lays, and its Rosensweig spike settings (see `doc.ferro`). */
|
|
153
|
+
export interface FerroSettings {
|
|
154
|
+
/** How much liquid ferrofluid each dab lays, scaled by coverage and flow (0..1, default 0: none). */
|
|
155
|
+
amount: number;
|
|
156
|
+
/** Capillary wavelength (spike-to-spike spacing) in pixels (4..64, default 16). */
|
|
157
|
+
wavelength: number;
|
|
158
|
+
/** Critical magnetic field |B| threshold where spikes begin to rise (0.01..0.95, default 0.12). */
|
|
159
|
+
threshold: number;
|
|
160
|
+
}
|
|
161
|
+
export declare const DEFAULT_FERRO: Readonly<FerroSettings>;
|
|
162
|
+
export declare function normalizeFerro(raw?: number | Partial<FerroSettings> | null | undefined, base?: FerroSettings): FerroSettings;
|
|
152
163
|
export declare function normalizeImpasto(raw?: Partial<ImpastoSettings>, base?: ImpastoSettings): ImpastoSettings;
|
|
153
164
|
/** Multi-coloured brush: `tip` lays the colours across the tip, `dab` changes colour from dab to dab. */
|
|
154
165
|
export type MultiColorMode = 'off' | 'tip' | 'dab';
|
|
@@ -283,6 +294,8 @@ export interface PaintBrush {
|
|
|
283
294
|
ghost?: GhostSettings;
|
|
284
295
|
/** Mutation paint settings (missing when not a mutation brush). */
|
|
285
296
|
mutation?: MutationSettings;
|
|
297
|
+
/** Ferrofluid paint: liquid ferrofluid it lays and its Rosensweig spike settings (amount 0: none). */
|
|
298
|
+
ferro: FerroSettings;
|
|
286
299
|
/**
|
|
287
300
|
* Dab engine: a stamp tip. Each dab (and each spray droplet) is this sticker's shape, an editor
|
|
288
301
|
* stamp (`editor:star`) or any sticker ref from the sticker library, laid in the paint colour;
|
|
@@ -321,7 +334,7 @@ export interface SpraySettings {
|
|
|
321
334
|
size: number;
|
|
322
335
|
}
|
|
323
336
|
export declare const DEFAULT_SPRAY: Readonly<SpraySettings>;
|
|
324
|
-
export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'paint' | 'light' | 'fluorescence' | 'thermochromic' | 'iridescence' | 'ghost' | 'mutation' | 'spray' | 'tipGrain' | 'livePatterns'>> & {
|
|
337
|
+
export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'paint' | 'light' | 'fluorescence' | 'thermochromic' | 'iridescence' | 'ghost' | 'mutation' | 'ferro' | 'spray' | 'tipGrain' | 'livePatterns'>> & {
|
|
325
338
|
spray?: Partial<SpraySettings> | null;
|
|
326
339
|
/** Tip grain (`null` removes it). */
|
|
327
340
|
tipGrain?: Partial<TipGrainSettings> | null;
|
|
@@ -336,6 +349,7 @@ export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mix
|
|
|
336
349
|
thermochromic?: Partial<ThermochromicSettings>;
|
|
337
350
|
/** Thin-film iridescence (`null` removes it). */
|
|
338
351
|
iridescence?: Partial<IridescenceSettings> | null;
|
|
352
|
+
ferro?: number | Partial<FerroSettings>;
|
|
339
353
|
/** A gradient (or `null` for the editor's paint); a plain colour source clears it. */
|
|
340
354
|
paint?: PaintSource | null;
|
|
341
355
|
tip?: Partial<BrushSettings>;
|
|
@@ -149,6 +149,17 @@ export interface MutationSettings {
|
|
|
149
149
|
}
|
|
150
150
|
export declare const DEFAULT_MUTATION: Readonly<MutationSettings>;
|
|
151
151
|
export declare function normalizeMutation(raw?: Partial<MutationSettings>, base?: MutationSettings): MutationSettings;
|
|
152
|
+
/** Ferrofluid paint: how much liquid ferrofluid a brush lays, and its Rosensweig spike settings (see `doc.ferro`). */
|
|
153
|
+
export interface FerroSettings {
|
|
154
|
+
/** How much liquid ferrofluid each dab lays, scaled by coverage and flow (0..1, default 0: none). */
|
|
155
|
+
amount: number;
|
|
156
|
+
/** Capillary wavelength (spike-to-spike spacing) in pixels (4..64, default 16). */
|
|
157
|
+
wavelength: number;
|
|
158
|
+
/** Critical magnetic field |B| threshold where spikes begin to rise (0.01..0.95, default 0.12). */
|
|
159
|
+
threshold: number;
|
|
160
|
+
}
|
|
161
|
+
export declare const DEFAULT_FERRO: Readonly<FerroSettings>;
|
|
162
|
+
export declare function normalizeFerro(raw?: number | Partial<FerroSettings> | null | undefined, base?: FerroSettings): FerroSettings;
|
|
152
163
|
export declare function normalizeImpasto(raw?: Partial<ImpastoSettings>, base?: ImpastoSettings): ImpastoSettings;
|
|
153
164
|
/** Multi-coloured brush: `tip` lays the colours across the tip, `dab` changes colour from dab to dab. */
|
|
154
165
|
export type MultiColorMode = 'off' | 'tip' | 'dab';
|
|
@@ -283,6 +294,8 @@ export interface PaintBrush {
|
|
|
283
294
|
ghost?: GhostSettings;
|
|
284
295
|
/** Mutation paint settings (missing when not a mutation brush). */
|
|
285
296
|
mutation?: MutationSettings;
|
|
297
|
+
/** Ferrofluid paint: liquid ferrofluid it lays and its Rosensweig spike settings (amount 0: none). */
|
|
298
|
+
ferro: FerroSettings;
|
|
286
299
|
/**
|
|
287
300
|
* Dab engine: a stamp tip. Each dab (and each spray droplet) is this sticker's shape, an editor
|
|
288
301
|
* stamp (`editor:star`) or any sticker ref from the sticker library, laid in the paint colour;
|
|
@@ -321,7 +334,7 @@ export interface SpraySettings {
|
|
|
321
334
|
size: number;
|
|
322
335
|
}
|
|
323
336
|
export declare const DEFAULT_SPRAY: Readonly<SpraySettings>;
|
|
324
|
-
export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'paint' | 'light' | 'fluorescence' | 'thermochromic' | 'iridescence' | 'ghost' | 'mutation' | 'spray' | 'tipGrain' | 'livePatterns'>> & {
|
|
337
|
+
export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'paint' | 'light' | 'fluorescence' | 'thermochromic' | 'iridescence' | 'ghost' | 'mutation' | 'ferro' | 'spray' | 'tipGrain' | 'livePatterns'>> & {
|
|
325
338
|
spray?: Partial<SpraySettings> | null;
|
|
326
339
|
/** Tip grain (`null` removes it). */
|
|
327
340
|
tipGrain?: Partial<TipGrainSettings> | null;
|
|
@@ -336,6 +349,7 @@ export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mix
|
|
|
336
349
|
thermochromic?: Partial<ThermochromicSettings>;
|
|
337
350
|
/** Thin-film iridescence (`null` removes it). */
|
|
338
351
|
iridescence?: Partial<IridescenceSettings> | null;
|
|
352
|
+
ferro?: number | Partial<FerroSettings>;
|
|
339
353
|
/** A gradient (or `null` for the editor's paint); a plain colour source clears it. */
|
|
340
354
|
paint?: PaintSource | null;
|
|
341
355
|
tip?: Partial<BrushSettings>;
|
|
@@ -23,7 +23,7 @@ import { type PaintBrushInput, type PaintBrush } from './brushes.cjs';
|
|
|
23
23
|
import { type BrushLibrary, type BrushLibraryFile } from '../brushes/library.cjs';
|
|
24
24
|
import { type BrushPatch, type UnsettableBrushFacet } from '../brushes/patch.cjs';
|
|
25
25
|
import type { Brush } from '../brushes/types.cjs';
|
|
26
|
-
import type
|
|
26
|
+
import { type ColorScheme, type ColorValue } from '../color/dual.cjs';
|
|
27
27
|
import { type PaintCanvas, type PaintDocumentState, type PaintLayer } from './document.cjs';
|
|
28
28
|
import { type ImageEncoder, type ImageFormat } from './encode.cjs';
|
|
29
29
|
import type { PenPoint } from './engine.cjs';
|
|
@@ -63,6 +63,7 @@ import type { PaintDirector } from './presence.cjs';
|
|
|
63
63
|
import type { PresenceActorInfo } from '../animation/presence.cjs';
|
|
64
64
|
import { type PaintProposals } from './collaboration.cjs';
|
|
65
65
|
import { type BreedStrokesResult, type ProposalGenomeResult, type StrokeMutationRates } from './evolution.cjs';
|
|
66
|
+
import { type PaintMagnet } from './ferro.cjs';
|
|
66
67
|
export declare class PaintEditorError extends Error {
|
|
67
68
|
constructor(message: string);
|
|
68
69
|
}
|
|
@@ -205,8 +206,8 @@ export interface LiveStrokeUpdate {
|
|
|
205
206
|
brushId?: string;
|
|
206
207
|
/** Brush settings to change (as `setBrush` takes), on top of `brushId` or the stroke's brush. */
|
|
207
208
|
brush?: Omit<PaintBrushInput, 'id'>;
|
|
208
|
-
/** A new colour #rrggbb (replaces gradient or effect paint). */
|
|
209
|
-
color?:
|
|
209
|
+
/** A new colour #rrggbb, or a light / dark pair (replaces gradient or effect paint). */
|
|
210
|
+
color?: ColorValue;
|
|
210
211
|
/** Paint: a colour, gradient paint or effect paint; `null` back to the plain colour. */
|
|
211
212
|
paint?: unknown;
|
|
212
213
|
/** Another jitter seed (particles, scatter and texture fall differently). */
|
|
@@ -274,8 +275,12 @@ export interface PaintPreviewPlacement {
|
|
|
274
275
|
export interface PaintStrokeInit {
|
|
275
276
|
/** Default the active layer. */
|
|
276
277
|
layerId?: string;
|
|
277
|
-
/**
|
|
278
|
-
|
|
278
|
+
/**
|
|
279
|
+
* Default the editor colour. A light / dark pair (`DualColor`) is recorded with the stroke
|
|
280
|
+
* (`RecordedStroke.dualColor`): on a stroke layer the document draws its light side and the view
|
|
281
|
+
* the viewer's (`setColorScheme`); on a pixel layer it paints the scheme's side.
|
|
282
|
+
*/
|
|
283
|
+
color?: ColorValue;
|
|
279
284
|
/**
|
|
280
285
|
* What this stroke paints with, instead of the editor's paint: a colour, gradient paint
|
|
281
286
|
* (`@pixerate/editor/paint` `PaintSource`), or effect paint (render it first with
|
|
@@ -548,6 +553,9 @@ export declare class PaintEditorController {
|
|
|
548
553
|
private readonly litCaches;
|
|
549
554
|
/** The live impasto stroke's channels. */
|
|
550
555
|
private liveThick;
|
|
556
|
+
/** The live ferrofluid stroke's channel. */
|
|
557
|
+
private liveFerro;
|
|
558
|
+
private nextMagnetId;
|
|
551
559
|
/** The UV / blacklight setting (saved with the document, not undo steps). */
|
|
552
560
|
private uvLight;
|
|
553
561
|
private readonly uvCaches;
|
|
@@ -1058,9 +1066,29 @@ export declare class PaintEditorController {
|
|
|
1058
1066
|
private brushColour;
|
|
1059
1067
|
/**
|
|
1060
1068
|
* The host's colour scheme: a paint colour that came from a brush's light / dark default
|
|
1061
|
-
* resolves to the new side
|
|
1069
|
+
* resolves to the new side, and stroke layers show their dual-colour strokes in it. Only the
|
|
1070
|
+
* view changes: the document, history and change listeners don't hear of it.
|
|
1062
1071
|
*/
|
|
1063
1072
|
setColorScheme(scheme: ColorScheme): void;
|
|
1073
|
+
/**
|
|
1074
|
+
* Stroke layers in the colour scheme: the document keeps every stroke layer drawn with each
|
|
1075
|
+
* stroke's `color` (a dual-colour stroke's light side), so saved and shared documents never
|
|
1076
|
+
* depend on who is looking. The view (display, image exports, the base a pointer stroke paints
|
|
1077
|
+
* on) draws dual-colour strokes in the scheme's side instead. One cached surface per layer,
|
|
1078
|
+
* brought up to date from the strokes that changed since it was drawn.
|
|
1079
|
+
*/
|
|
1080
|
+
private schemeViews;
|
|
1081
|
+
private schemeCopies;
|
|
1082
|
+
/** Set while a stroke is painted for the document rather than the view (`runStroke` on a stroke layer): dual colours take this side. */
|
|
1083
|
+
private paintScheme;
|
|
1084
|
+
/** A stroke as the scheme shows it: itself, or (a dual-colour stroke) a copy in the scheme's side. */
|
|
1085
|
+
private schemeStroke;
|
|
1086
|
+
/** A stroke layer's surface in the scheme, or `null` when the document's pixels already show it. */
|
|
1087
|
+
private schemeSurface;
|
|
1088
|
+
/** `layers` with each stroke layer that holds dual-colour strokes shown in the scheme. */
|
|
1089
|
+
private schemeLayers;
|
|
1090
|
+
/** The paint colour's light / dark pair for a stroke with `brushId`, when the colour came from one (a brush's own or default colour, or `setColor`). */
|
|
1091
|
+
private dualPaint;
|
|
1064
1092
|
/** Locks the paint colour: choosing a brush with a default colour keeps it. Editor state, not an undo step. */
|
|
1065
1093
|
setColorLocked(locked: boolean): void;
|
|
1066
1094
|
/**
|
|
@@ -1071,8 +1099,12 @@ export declare class PaintEditorController {
|
|
|
1071
1099
|
private takeBrushColour;
|
|
1072
1100
|
/** A brush that always paints its own colour (`colour.own`): that colour, resolved for the scheme now; else `null`. */
|
|
1073
1101
|
private ownColour;
|
|
1074
|
-
/**
|
|
1075
|
-
|
|
1102
|
+
/**
|
|
1103
|
+
* Sets the paint colour (and goes back to one colour from gradient paint). A light / dark pair
|
|
1104
|
+
* paints the colour scheme's side, follows `setColorScheme`, and is recorded with each stroke
|
|
1105
|
+
* painted in it. Returns the colour as #rrggbb.
|
|
1106
|
+
*/
|
|
1107
|
+
setColor(color: ColorValue): string;
|
|
1076
1108
|
/**
|
|
1077
1109
|
* Sets what strokes paint with: one colour (`{ type: 'color', color }` or `#rrggbb`), or gradient
|
|
1078
1110
|
* paint (`{ type: 'gradient', stops, space?, map?, softness? }`, see `@pixerate/editor/paint`),
|
|
@@ -1286,6 +1318,51 @@ export declare class PaintEditorController {
|
|
|
1286
1318
|
layerId: string;
|
|
1287
1319
|
flattened: boolean;
|
|
1288
1320
|
};
|
|
1321
|
+
/** The document's `ferro` and `ferroSettings` without these layers. */
|
|
1322
|
+
private ferroWithout;
|
|
1323
|
+
/** Runs deterministic advection on all pixel layers with liquid ferrofluid toward `magnets`. */
|
|
1324
|
+
private advectDocumentFerro;
|
|
1325
|
+
/** Lists the magnets on the canvas. */
|
|
1326
|
+
listMagnets(): PaintMagnet[];
|
|
1327
|
+
/** Places a dipole magnet on the canvas and advects liquid ferrofluid toward it (one undo step). */
|
|
1328
|
+
addMagnet(input: {
|
|
1329
|
+
x: number;
|
|
1330
|
+
y: number;
|
|
1331
|
+
strength?: number;
|
|
1332
|
+
radius?: number;
|
|
1333
|
+
}): PaintMagnet;
|
|
1334
|
+
/** Moves or retunes a magnet and advects liquid ferrofluid toward the magnets (one undo step). */
|
|
1335
|
+
updateMagnet(id: string, update: {
|
|
1336
|
+
x?: number;
|
|
1337
|
+
y?: number;
|
|
1338
|
+
strength?: number;
|
|
1339
|
+
radius?: number;
|
|
1340
|
+
}, commitToHistory?: boolean): PaintMagnet;
|
|
1341
|
+
/** Removes magnets by id, or all magnets when `ids` is omitted or empty (one undo step). Returns the removed ids. */
|
|
1342
|
+
removeMagnets(ids?: readonly string[]): string[];
|
|
1343
|
+
/** Replaces the canvas magnets (used by replay). */
|
|
1344
|
+
replaceMagnets(magnets: readonly PaintMagnet[], advect?: boolean): void;
|
|
1345
|
+
/** Reads a layer's liquid ferrofluid coverage and active Rosensweig spike relief under the canvas magnets. */
|
|
1346
|
+
getFerrofluid(layerId?: string): {
|
|
1347
|
+
layerId: string;
|
|
1348
|
+
ferro: boolean;
|
|
1349
|
+
bounds: RasterRect | null;
|
|
1350
|
+
peak: number;
|
|
1351
|
+
coverage: number;
|
|
1352
|
+
activeSpikeArea: number;
|
|
1353
|
+
maxSpikeHeight: number;
|
|
1354
|
+
magnetCount: number;
|
|
1355
|
+
wavelength: number;
|
|
1356
|
+
threshold: number;
|
|
1357
|
+
};
|
|
1358
|
+
/** Cures a layer's liquid ferrofluid: bakes the current Rosensweig spikes and glossy metallic material into `doc.thick` and clears `doc.ferro` (one undo step). */
|
|
1359
|
+
cureFerrofluid(layerId?: string): {
|
|
1360
|
+
layerId: string;
|
|
1361
|
+
cured: boolean;
|
|
1362
|
+
bounds: RasterRect | null;
|
|
1363
|
+
maxSpikeHeight: number;
|
|
1364
|
+
activeSpikeArea: number;
|
|
1365
|
+
};
|
|
1289
1366
|
/**
|
|
1290
1367
|
* A fresh, headless editor for replaying this painting at `scale` (canvas, dpi and paper grain
|
|
1291
1368
|
* scaled; every pixel layer empty; the same brushes, lighting and wet options). Dispose of it
|
|
@@ -1477,7 +1554,7 @@ export declare class PaintEditorController {
|
|
|
1477
1554
|
* Linear Dodge (`::uv`) spill layer directly above it.
|
|
1478
1555
|
*/
|
|
1479
1556
|
private uvLayers;
|
|
1480
|
-
/** The layers with thick paint lit (each thick layer's pixels replaced by its lit tiles). */
|
|
1557
|
+
/** The layers with thick paint and ferrofluid spikes lit (each thick or ferrofluid layer's pixels replaced by its lit tiles). */
|
|
1481
1558
|
private litLayers;
|
|
1482
1559
|
/**
|
|
1483
1560
|
* Light paint over the (lit) layers: glow, rim and clarity in each layer's pixels, and its spill
|
|
@@ -1726,6 +1803,10 @@ export declare class PaintEditorController {
|
|
|
1726
1803
|
liveStrokeArea(id: string): RasterRect | null;
|
|
1727
1804
|
/** Commits a layer's new stroke list with its redrawn pixels, recorded for replays (one undo step). */
|
|
1728
1805
|
private commitLiveStrokes;
|
|
1806
|
+
/**
|
|
1807
|
+
* The document with a layer's strokes set and its pixels redrawn. With `record` false (the same
|
|
1808
|
+
* strokes drawn for the colour scheme) the pixel lock doesn't apply and no event is recorded for replays.
|
|
1809
|
+
*/
|
|
1729
1810
|
private withLiveStrokes;
|
|
1730
1811
|
/** Where a stroke painted (document pixels): as learnt when it was painted or drawn, else an estimate from its points and brush. */
|
|
1731
1812
|
private strokeArea;
|
|
@@ -23,7 +23,7 @@ import { type PaintBrushInput, type PaintBrush } from './brushes.js';
|
|
|
23
23
|
import { type BrushLibrary, type BrushLibraryFile } from '../brushes/library.js';
|
|
24
24
|
import { type BrushPatch, type UnsettableBrushFacet } from '../brushes/patch.js';
|
|
25
25
|
import type { Brush } from '../brushes/types.js';
|
|
26
|
-
import type
|
|
26
|
+
import { type ColorScheme, type ColorValue } from '../color/dual.js';
|
|
27
27
|
import { type PaintCanvas, type PaintDocumentState, type PaintLayer } from './document.js';
|
|
28
28
|
import { type ImageEncoder, type ImageFormat } from './encode.js';
|
|
29
29
|
import type { PenPoint } from './engine.js';
|
|
@@ -63,6 +63,7 @@ import type { PaintDirector } from './presence.js';
|
|
|
63
63
|
import type { PresenceActorInfo } from '../animation/presence.js';
|
|
64
64
|
import { type PaintProposals } from './collaboration.js';
|
|
65
65
|
import { type BreedStrokesResult, type ProposalGenomeResult, type StrokeMutationRates } from './evolution.js';
|
|
66
|
+
import { type PaintMagnet } from './ferro.js';
|
|
66
67
|
export declare class PaintEditorError extends Error {
|
|
67
68
|
constructor(message: string);
|
|
68
69
|
}
|
|
@@ -205,8 +206,8 @@ export interface LiveStrokeUpdate {
|
|
|
205
206
|
brushId?: string;
|
|
206
207
|
/** Brush settings to change (as `setBrush` takes), on top of `brushId` or the stroke's brush. */
|
|
207
208
|
brush?: Omit<PaintBrushInput, 'id'>;
|
|
208
|
-
/** A new colour #rrggbb (replaces gradient or effect paint). */
|
|
209
|
-
color?:
|
|
209
|
+
/** A new colour #rrggbb, or a light / dark pair (replaces gradient or effect paint). */
|
|
210
|
+
color?: ColorValue;
|
|
210
211
|
/** Paint: a colour, gradient paint or effect paint; `null` back to the plain colour. */
|
|
211
212
|
paint?: unknown;
|
|
212
213
|
/** Another jitter seed (particles, scatter and texture fall differently). */
|
|
@@ -274,8 +275,12 @@ export interface PaintPreviewPlacement {
|
|
|
274
275
|
export interface PaintStrokeInit {
|
|
275
276
|
/** Default the active layer. */
|
|
276
277
|
layerId?: string;
|
|
277
|
-
/**
|
|
278
|
-
|
|
278
|
+
/**
|
|
279
|
+
* Default the editor colour. A light / dark pair (`DualColor`) is recorded with the stroke
|
|
280
|
+
* (`RecordedStroke.dualColor`): on a stroke layer the document draws its light side and the view
|
|
281
|
+
* the viewer's (`setColorScheme`); on a pixel layer it paints the scheme's side.
|
|
282
|
+
*/
|
|
283
|
+
color?: ColorValue;
|
|
279
284
|
/**
|
|
280
285
|
* What this stroke paints with, instead of the editor's paint: a colour, gradient paint
|
|
281
286
|
* (`@pixerate/editor/paint` `PaintSource`), or effect paint (render it first with
|
|
@@ -548,6 +553,9 @@ export declare class PaintEditorController {
|
|
|
548
553
|
private readonly litCaches;
|
|
549
554
|
/** The live impasto stroke's channels. */
|
|
550
555
|
private liveThick;
|
|
556
|
+
/** The live ferrofluid stroke's channel. */
|
|
557
|
+
private liveFerro;
|
|
558
|
+
private nextMagnetId;
|
|
551
559
|
/** The UV / blacklight setting (saved with the document, not undo steps). */
|
|
552
560
|
private uvLight;
|
|
553
561
|
private readonly uvCaches;
|
|
@@ -1058,9 +1066,29 @@ export declare class PaintEditorController {
|
|
|
1058
1066
|
private brushColour;
|
|
1059
1067
|
/**
|
|
1060
1068
|
* The host's colour scheme: a paint colour that came from a brush's light / dark default
|
|
1061
|
-
* resolves to the new side
|
|
1069
|
+
* resolves to the new side, and stroke layers show their dual-colour strokes in it. Only the
|
|
1070
|
+
* view changes: the document, history and change listeners don't hear of it.
|
|
1062
1071
|
*/
|
|
1063
1072
|
setColorScheme(scheme: ColorScheme): void;
|
|
1073
|
+
/**
|
|
1074
|
+
* Stroke layers in the colour scheme: the document keeps every stroke layer drawn with each
|
|
1075
|
+
* stroke's `color` (a dual-colour stroke's light side), so saved and shared documents never
|
|
1076
|
+
* depend on who is looking. The view (display, image exports, the base a pointer stroke paints
|
|
1077
|
+
* on) draws dual-colour strokes in the scheme's side instead. One cached surface per layer,
|
|
1078
|
+
* brought up to date from the strokes that changed since it was drawn.
|
|
1079
|
+
*/
|
|
1080
|
+
private schemeViews;
|
|
1081
|
+
private schemeCopies;
|
|
1082
|
+
/** Set while a stroke is painted for the document rather than the view (`runStroke` on a stroke layer): dual colours take this side. */
|
|
1083
|
+
private paintScheme;
|
|
1084
|
+
/** A stroke as the scheme shows it: itself, or (a dual-colour stroke) a copy in the scheme's side. */
|
|
1085
|
+
private schemeStroke;
|
|
1086
|
+
/** A stroke layer's surface in the scheme, or `null` when the document's pixels already show it. */
|
|
1087
|
+
private schemeSurface;
|
|
1088
|
+
/** `layers` with each stroke layer that holds dual-colour strokes shown in the scheme. */
|
|
1089
|
+
private schemeLayers;
|
|
1090
|
+
/** The paint colour's light / dark pair for a stroke with `brushId`, when the colour came from one (a brush's own or default colour, or `setColor`). */
|
|
1091
|
+
private dualPaint;
|
|
1064
1092
|
/** Locks the paint colour: choosing a brush with a default colour keeps it. Editor state, not an undo step. */
|
|
1065
1093
|
setColorLocked(locked: boolean): void;
|
|
1066
1094
|
/**
|
|
@@ -1071,8 +1099,12 @@ export declare class PaintEditorController {
|
|
|
1071
1099
|
private takeBrushColour;
|
|
1072
1100
|
/** A brush that always paints its own colour (`colour.own`): that colour, resolved for the scheme now; else `null`. */
|
|
1073
1101
|
private ownColour;
|
|
1074
|
-
/**
|
|
1075
|
-
|
|
1102
|
+
/**
|
|
1103
|
+
* Sets the paint colour (and goes back to one colour from gradient paint). A light / dark pair
|
|
1104
|
+
* paints the colour scheme's side, follows `setColorScheme`, and is recorded with each stroke
|
|
1105
|
+
* painted in it. Returns the colour as #rrggbb.
|
|
1106
|
+
*/
|
|
1107
|
+
setColor(color: ColorValue): string;
|
|
1076
1108
|
/**
|
|
1077
1109
|
* Sets what strokes paint with: one colour (`{ type: 'color', color }` or `#rrggbb`), or gradient
|
|
1078
1110
|
* paint (`{ type: 'gradient', stops, space?, map?, softness? }`, see `@pixerate/editor/paint`),
|
|
@@ -1286,6 +1318,51 @@ export declare class PaintEditorController {
|
|
|
1286
1318
|
layerId: string;
|
|
1287
1319
|
flattened: boolean;
|
|
1288
1320
|
};
|
|
1321
|
+
/** The document's `ferro` and `ferroSettings` without these layers. */
|
|
1322
|
+
private ferroWithout;
|
|
1323
|
+
/** Runs deterministic advection on all pixel layers with liquid ferrofluid toward `magnets`. */
|
|
1324
|
+
private advectDocumentFerro;
|
|
1325
|
+
/** Lists the magnets on the canvas. */
|
|
1326
|
+
listMagnets(): PaintMagnet[];
|
|
1327
|
+
/** Places a dipole magnet on the canvas and advects liquid ferrofluid toward it (one undo step). */
|
|
1328
|
+
addMagnet(input: {
|
|
1329
|
+
x: number;
|
|
1330
|
+
y: number;
|
|
1331
|
+
strength?: number;
|
|
1332
|
+
radius?: number;
|
|
1333
|
+
}): PaintMagnet;
|
|
1334
|
+
/** Moves or retunes a magnet and advects liquid ferrofluid toward the magnets (one undo step). */
|
|
1335
|
+
updateMagnet(id: string, update: {
|
|
1336
|
+
x?: number;
|
|
1337
|
+
y?: number;
|
|
1338
|
+
strength?: number;
|
|
1339
|
+
radius?: number;
|
|
1340
|
+
}, commitToHistory?: boolean): PaintMagnet;
|
|
1341
|
+
/** Removes magnets by id, or all magnets when `ids` is omitted or empty (one undo step). Returns the removed ids. */
|
|
1342
|
+
removeMagnets(ids?: readonly string[]): string[];
|
|
1343
|
+
/** Replaces the canvas magnets (used by replay). */
|
|
1344
|
+
replaceMagnets(magnets: readonly PaintMagnet[], advect?: boolean): void;
|
|
1345
|
+
/** Reads a layer's liquid ferrofluid coverage and active Rosensweig spike relief under the canvas magnets. */
|
|
1346
|
+
getFerrofluid(layerId?: string): {
|
|
1347
|
+
layerId: string;
|
|
1348
|
+
ferro: boolean;
|
|
1349
|
+
bounds: RasterRect | null;
|
|
1350
|
+
peak: number;
|
|
1351
|
+
coverage: number;
|
|
1352
|
+
activeSpikeArea: number;
|
|
1353
|
+
maxSpikeHeight: number;
|
|
1354
|
+
magnetCount: number;
|
|
1355
|
+
wavelength: number;
|
|
1356
|
+
threshold: number;
|
|
1357
|
+
};
|
|
1358
|
+
/** Cures a layer's liquid ferrofluid: bakes the current Rosensweig spikes and glossy metallic material into `doc.thick` and clears `doc.ferro` (one undo step). */
|
|
1359
|
+
cureFerrofluid(layerId?: string): {
|
|
1360
|
+
layerId: string;
|
|
1361
|
+
cured: boolean;
|
|
1362
|
+
bounds: RasterRect | null;
|
|
1363
|
+
maxSpikeHeight: number;
|
|
1364
|
+
activeSpikeArea: number;
|
|
1365
|
+
};
|
|
1289
1366
|
/**
|
|
1290
1367
|
* A fresh, headless editor for replaying this painting at `scale` (canvas, dpi and paper grain
|
|
1291
1368
|
* scaled; every pixel layer empty; the same brushes, lighting and wet options). Dispose of it
|
|
@@ -1477,7 +1554,7 @@ export declare class PaintEditorController {
|
|
|
1477
1554
|
* Linear Dodge (`::uv`) spill layer directly above it.
|
|
1478
1555
|
*/
|
|
1479
1556
|
private uvLayers;
|
|
1480
|
-
/** The layers with thick paint lit (each thick layer's pixels replaced by its lit tiles). */
|
|
1557
|
+
/** The layers with thick paint and ferrofluid spikes lit (each thick or ferrofluid layer's pixels replaced by its lit tiles). */
|
|
1481
1558
|
private litLayers;
|
|
1482
1559
|
/**
|
|
1483
1560
|
* Light paint over the (lit) layers: glow, rim and clarity in each layer's pixels, and its spill
|
|
@@ -1726,6 +1803,10 @@ export declare class PaintEditorController {
|
|
|
1726
1803
|
liveStrokeArea(id: string): RasterRect | null;
|
|
1727
1804
|
/** Commits a layer's new stroke list with its redrawn pixels, recorded for replays (one undo step). */
|
|
1728
1805
|
private commitLiveStrokes;
|
|
1806
|
+
/**
|
|
1807
|
+
* The document with a layer's strokes set and its pixels redrawn. With `record` false (the same
|
|
1808
|
+
* strokes drawn for the colour scheme) the pixel lock doesn't apply and no event is recorded for replays.
|
|
1809
|
+
*/
|
|
1729
1810
|
private withLiveStrokes;
|
|
1730
1811
|
/** Where a stroke painted (document pixels): as learnt when it was painted or drawn, else an estimate from its points and brush. */
|
|
1731
1812
|
private strokeArea;
|
|
@@ -13,6 +13,7 @@ import { type PaperSettings } from './paper.cjs';
|
|
|
13
13
|
import type { RecordedStroke } from './strokes.cjs';
|
|
14
14
|
import type { WetEvent } from './wet.cjs';
|
|
15
15
|
import type { ThickChannels } from './thick.cjs';
|
|
16
|
+
import type { FerroSettings, PaintMagnet } from './ferro.cjs';
|
|
16
17
|
import type { Sticker } from './stickers.cjs';
|
|
17
18
|
import type { PaintEffectSource, PaintPaperEffect } from './effects.cjs';
|
|
18
19
|
import type { HeatField } from './heat.cjs';
|
|
@@ -61,6 +62,12 @@ export interface PaintDocumentState {
|
|
|
61
62
|
thermo?: Readonly<Record<string, TiledSurface>>;
|
|
62
63
|
/** Coarse document-level heat field (1/4 resolution) for thermochromic ink and wet-paint drying. See `heat.ts`. */
|
|
63
64
|
heat?: HeatField;
|
|
65
|
+
/** Ferrofluid paint: each layer's liquid ferrofluid channel, 0..255 per pixel in layer space (layers without ferrofluid are missing). See `ferro.ts`. */
|
|
66
|
+
ferro?: Readonly<Record<string, TiledSurface>>;
|
|
67
|
+
/** Per-layer Rosensweig spike settings (`wavelength`, `threshold`) from the last ferrofluid stroke on that layer. */
|
|
68
|
+
ferroSettings?: Readonly<Record<string, FerroSettings>>;
|
|
69
|
+
/** Dipole magnets placed on the canvas (document pixel coordinates). */
|
|
70
|
+
magnets?: PaintMagnet[];
|
|
64
71
|
/** Thick paint: each layer's height and material channels (layers without relief are missing). */
|
|
65
72
|
thick?: Readonly<Record<string, ThickChannels>>;
|
|
66
73
|
/** Effect layers: the provider effect each one is drawn from (layers that are gone are ignored). */
|
|
@@ -79,7 +86,7 @@ export interface PaintDocumentState {
|
|
|
79
86
|
/** A change a replay repeats besides strokes, recorded with how many strokes came before it. */
|
|
80
87
|
export interface PaintEvent {
|
|
81
88
|
at: number;
|
|
82
|
-
kind: 'fill' | 'fill-region' | 'clear' | 'flatten' | 'stickers' | 'live-strokes';
|
|
89
|
+
kind: 'fill' | 'fill-region' | 'clear' | 'flatten' | 'stickers' | 'live-strokes' | 'magnets' | 'cure-ferrofluid';
|
|
83
90
|
layerId: string;
|
|
84
91
|
/** The fill's options (colour, opacity, grain, pressure, blend), or the layer's stickers or live strokes after an edit. */
|
|
85
92
|
data?: Record<string, unknown>;
|
|
@@ -13,6 +13,7 @@ import { type PaperSettings } from './paper.js';
|
|
|
13
13
|
import type { RecordedStroke } from './strokes.js';
|
|
14
14
|
import type { WetEvent } from './wet.js';
|
|
15
15
|
import type { ThickChannels } from './thick.js';
|
|
16
|
+
import type { FerroSettings, PaintMagnet } from './ferro.js';
|
|
16
17
|
import type { Sticker } from './stickers.js';
|
|
17
18
|
import type { PaintEffectSource, PaintPaperEffect } from './effects.js';
|
|
18
19
|
import type { HeatField } from './heat.js';
|
|
@@ -61,6 +62,12 @@ export interface PaintDocumentState {
|
|
|
61
62
|
thermo?: Readonly<Record<string, TiledSurface>>;
|
|
62
63
|
/** Coarse document-level heat field (1/4 resolution) for thermochromic ink and wet-paint drying. See `heat.ts`. */
|
|
63
64
|
heat?: HeatField;
|
|
65
|
+
/** Ferrofluid paint: each layer's liquid ferrofluid channel, 0..255 per pixel in layer space (layers without ferrofluid are missing). See `ferro.ts`. */
|
|
66
|
+
ferro?: Readonly<Record<string, TiledSurface>>;
|
|
67
|
+
/** Per-layer Rosensweig spike settings (`wavelength`, `threshold`) from the last ferrofluid stroke on that layer. */
|
|
68
|
+
ferroSettings?: Readonly<Record<string, FerroSettings>>;
|
|
69
|
+
/** Dipole magnets placed on the canvas (document pixel coordinates). */
|
|
70
|
+
magnets?: PaintMagnet[];
|
|
64
71
|
/** Thick paint: each layer's height and material channels (layers without relief are missing). */
|
|
65
72
|
thick?: Readonly<Record<string, ThickChannels>>;
|
|
66
73
|
/** Effect layers: the provider effect each one is drawn from (layers that are gone are ignored). */
|
|
@@ -79,7 +86,7 @@ export interface PaintDocumentState {
|
|
|
79
86
|
/** A change a replay repeats besides strokes, recorded with how many strokes came before it. */
|
|
80
87
|
export interface PaintEvent {
|
|
81
88
|
at: number;
|
|
82
|
-
kind: 'fill' | 'fill-region' | 'clear' | 'flatten' | 'stickers' | 'live-strokes';
|
|
89
|
+
kind: 'fill' | 'fill-region' | 'clear' | 'flatten' | 'stickers' | 'live-strokes' | 'magnets' | 'cure-ferrofluid';
|
|
83
90
|
layerId: string;
|
|
84
91
|
/** The fill's options (colour, opacity, grain, pressure, blend), or the layer's stickers or live strokes after an edit. */
|
|
85
92
|
data?: Record<string, unknown>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for ferrofluid paint and magnets: ferrofluid strokes are painted with `paint_stroke`
|
|
3
|
+
* and a brush whose `ferro.amount` is above 0 (`ferrofluid`, `ferro-ink`); these tools place,
|
|
4
|
+
* move and remove magnets (`add_magnet`, `update_magnet`, `remove_magnets`, `list_magnets`), read
|
|
5
|
+
* a layer's liquid ferrofluid and live Rosensweig spike stats (`get_ferrofluid`), and cure the
|
|
6
|
+
* liquid spikes into solid impasto relief (`cure_ferrofluid`).
|
|
7
|
+
*/
|
|
8
|
+
import type { PaintAgentTool } from './hosted.cjs';
|
|
9
|
+
import type { PaintEditorController } from './controller.cjs';
|
|
10
|
+
export declare function createFerroTools(c: PaintEditorController): PaintAgentTool[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for ferrofluid paint and magnets: ferrofluid strokes are painted with `paint_stroke`
|
|
3
|
+
* and a brush whose `ferro.amount` is above 0 (`ferrofluid`, `ferro-ink`); these tools place,
|
|
4
|
+
* move and remove magnets (`add_magnet`, `update_magnet`, `remove_magnets`, `list_magnets`), read
|
|
5
|
+
* a layer's liquid ferrofluid and live Rosensweig spike stats (`get_ferrofluid`), and cure the
|
|
6
|
+
* liquid spikes into solid impasto relief (`cure_ferrofluid`).
|
|
7
|
+
*/
|
|
8
|
+
import type { PaintAgentTool } from './hosted.js';
|
|
9
|
+
import type { PaintEditorController } from './controller.js';
|
|
10
|
+
export declare function createFerroTools(c: PaintEditorController): PaintAgentTool[];
|