@pixerate/editor 0.273.0 → 0.275.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 +60 -60
- package/dist/animation-editor/index.js +4 -4
- package/dist/brushes/index.cjs +102 -74
- package/dist/brushes/index.js +34 -6
- package/dist/brushes/patch.d.cts +1 -1
- package/dist/brushes/patch.d.ts +1 -1
- package/dist/brushes/preview.d.cts +3 -0
- package/dist/brushes/preview.d.ts +3 -0
- package/dist/brushes/profiles.d.cts +2 -0
- package/dist/brushes/profiles.d.ts +2 -0
- package/dist/brushes/schema.d.cts +4 -0
- package/dist/brushes/schema.d.ts +4 -0
- package/dist/brushes/types.d.cts +47 -0
- package/dist/brushes/types.d.ts +47 -0
- package/dist/{brushstrokeRender-5YBCLFDQ.cjs → brushstrokeRender-2RQL46WB.cjs} +15 -15
- package/dist/{brushstrokeRender-DZGFU3J4.js → brushstrokeRender-WGY4DZHF.js} +3 -3
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-2XDNF73E.js → chunk-43XJC3PP.js} +1 -1
- package/dist/{chunk-GHGBIAWQ.cjs → chunk-6QNDGMK7.cjs} +263 -45
- package/dist/{chunk-2F3YDXCN.js → chunk-75SYKUOT.js} +1 -1
- package/dist/{chunk-M3RZOF3G.cjs → chunk-C6VB7CPY.cjs} +1 -1
- package/dist/{chunk-N5IMDAHM.cjs → chunk-DHC4E2DU.cjs} +89 -37
- package/dist/{chunk-NAHJV3O6.js → chunk-G5TCMKX5.js} +28 -11
- package/dist/{chunk-DZVRH63Y.js → chunk-IEEY5RJV.js} +1 -1
- package/dist/{chunk-7W2EQQBP.cjs → chunk-JDXWLCXF.cjs} +6 -6
- package/dist/{chunk-N3SKPQEH.js → chunk-LMG57L5A.js} +62 -10
- package/dist/{chunk-5HP2VSAS.js → chunk-MSWLJI4G.js} +1 -1
- package/dist/{chunk-SNAFFCAX.cjs → chunk-OLZXXAER.cjs} +221 -196
- package/dist/{chunk-YJANF2BL.cjs → chunk-RAPNRK4R.cjs} +86 -86
- package/dist/{chunk-CLB2I2FU.js → chunk-RJGW3RQS.js} +2 -2
- package/dist/{chunk-FXVCB6YG.cjs → chunk-T6KNJVBP.cjs} +35 -35
- package/dist/{chunk-ZEI7ZEA4.js → chunk-Y2ISSVPH.js} +34 -9
- package/dist/{chunk-3JKCREEU.cjs → chunk-Y354ETAE.cjs} +76 -59
- package/dist/{chunk-TNLKFW7D.cjs → chunk-YYZC2EQO.cjs} +23 -23
- package/dist/{chunk-UXYCY3HP.js → chunk-ZM7IKQ4X.js} +239 -21
- package/dist/image-editor/index.cjs +789 -789
- package/dist/image-editor/index.js +5 -5
- package/dist/paint/index.cjs +2 -2
- package/dist/paint/index.js +1 -1
- package/dist/paint/wet/world.d.cts +15 -2
- package/dist/paint/wet/world.d.ts +15 -2
- package/dist/paint-editor/brush-controls.d.cts +7 -0
- package/dist/paint-editor/brush-controls.d.ts +7 -0
- package/dist/paint-editor/brush-model.d.cts +59 -1
- package/dist/paint-editor/brush-model.d.ts +59 -1
- package/dist/paint-editor/collaboration.d.cts +6 -1
- package/dist/paint-editor/collaboration.d.ts +6 -1
- package/dist/paint-editor/controller.d.cts +199 -1
- package/dist/paint-editor/controller.d.ts +199 -1
- package/dist/paint-editor/dab-stroke.d.cts +3 -0
- package/dist/paint-editor/dab-stroke.d.ts +3 -0
- package/dist/paint-editor/document.d.cts +13 -3
- package/dist/paint-editor/document.d.ts +13 -3
- package/dist/paint-editor/engine.d.cts +3 -0
- package/dist/paint-editor/engine.d.ts +3 -0
- package/dist/paint-editor/evolution-tools.d.cts +48 -0
- package/dist/paint-editor/evolution-tools.d.ts +48 -0
- package/dist/paint-editor/evolution.d.cts +175 -0
- package/dist/paint-editor/evolution.d.ts +175 -0
- package/dist/paint-editor/heat.d.cts +156 -0
- package/dist/paint-editor/heat.d.ts +156 -0
- package/dist/paint-editor/index.cjs +4905 -1525
- package/dist/paint-editor/index.d.cts +5 -0
- package/dist/paint-editor/index.d.ts +5 -0
- package/dist/paint-editor/index.js +10952 -7572
- package/dist/paint-editor/mutation-tools.d.cts +13 -0
- package/dist/paint-editor/mutation-tools.d.ts +13 -0
- package/dist/paint-editor/mutation.d.cts +67 -0
- package/dist/paint-editor/mutation.d.ts +67 -0
- package/dist/paint-editor/presence.d.cts +7 -1
- package/dist/paint-editor/presence.d.ts +7 -1
- package/dist/paint-editor/procedural.d.cts +3 -0
- package/dist/paint-editor/procedural.d.ts +3 -0
- package/dist/paint-editor/stroke.d.cts +32 -2
- package/dist/paint-editor/stroke.d.ts +32 -2
- package/dist/paint-editor/thick.d.cts +48 -7
- package/dist/paint-editor/thick.d.ts +48 -7
- package/dist/paint-editor/ui.d.cts +36 -1
- package/dist/paint-editor/ui.d.ts +36 -1
- package/dist/paint-editor/wet.d.cts +8 -1
- package/dist/paint-editor/wet.d.ts +8 -1
- package/dist/vector/index.cjs +999 -999
- package/dist/vector/index.js +5 -5
- package/package.json +1 -1
- package/skills/README.md +1 -0
- package/skills/pixerate-brushes/SKILL.md +3 -0
- package/skills/pixerate-paint-editor/SKILL.md +36 -53
- package/skills/pixerate-paint-editor/references/brush-facets.md +3 -0
- package/skills/pixerate-paint-editor/references/mutation.md +25 -0
- package/skills/pixerate-paint-editor/references/oils.md +8 -1
- package/skills/pixerate-paint-editor/references/smart-inks.md +51 -0
- package/skills/pixerate-paint-mutation/SKILL.md +76 -0
- package/skills/pixerate-paint-mutation/evals/decline-unanswered.json +58 -0
- package/skills/pixerate-paint-mutation/evals/dry-ink-answer.json +74 -0
- package/skills/pixerate-paint-mutation/evals/wet-wash-answer.json +76 -0
- package/skills/pixerate-paint-oil-impasto/SKILL.md +2 -1
|
@@ -20,6 +20,7 @@ import type { PaintBrush } from './brushes.cjs';
|
|
|
20
20
|
import { type EffectPaintPixels } from './effect-paint.cjs';
|
|
21
21
|
import type { StickerArtLookup } from './sticker-art.cjs';
|
|
22
22
|
import { type PaperGrain } from './paper.cjs';
|
|
23
|
+
import type { FilmBuffer } from './thick.cjs';
|
|
23
24
|
/** One pen sample in document pixels. Every channel but x and y is optional. */
|
|
24
25
|
export interface PenPoint {
|
|
25
26
|
x: number;
|
|
@@ -136,6 +137,8 @@ export interface DryStrokeOptions {
|
|
|
136
137
|
* tip grain (`brush.tipGrain.source`); without it such a tip paints round, and the grain is left out.
|
|
137
138
|
*/
|
|
138
139
|
stampArt?: StickerArtLookup;
|
|
140
|
+
/** Thin-film iridescence channel for dry brushes with `iridescence` (or eraser). */
|
|
141
|
+
film?: FilmBuffer | null;
|
|
139
142
|
}
|
|
140
143
|
/**
|
|
141
144
|
* One dab-engine stroke (dab and eraser brushes): smoothing, the dab walk of every copy, grain and
|
|
@@ -20,6 +20,7 @@ import type { PaintBrush } from './brushes.js';
|
|
|
20
20
|
import { type EffectPaintPixels } from './effect-paint.js';
|
|
21
21
|
import type { StickerArtLookup } from './sticker-art.js';
|
|
22
22
|
import { type PaperGrain } from './paper.js';
|
|
23
|
+
import type { FilmBuffer } from './thick.js';
|
|
23
24
|
/** One pen sample in document pixels. Every channel but x and y is optional. */
|
|
24
25
|
export interface PenPoint {
|
|
25
26
|
x: number;
|
|
@@ -136,6 +137,8 @@ export interface DryStrokeOptions {
|
|
|
136
137
|
* tip grain (`brush.tipGrain.source`); without it such a tip paints round, and the grain is left out.
|
|
137
138
|
*/
|
|
138
139
|
stampArt?: StickerArtLookup;
|
|
140
|
+
/** Thin-film iridescence channel for dry brushes with `iridescence` (or eraser). */
|
|
141
|
+
film?: FilmBuffer | null;
|
|
139
142
|
}
|
|
140
143
|
/**
|
|
141
144
|
* One dab-engine stroke (dab and eraser brushes): smoothing, the dab walk of every copy, grain and
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for evolutionary strokes (`breed_strokes`, `breed_proposal`, `get_proposal_genome`).
|
|
3
|
+
* Accepting or dismissing bred variants reuses `accept_paint_proposal` and `reject_paint_proposal`.
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentToolProvider } from '../tools/registry.cjs';
|
|
6
|
+
import type { PaintEditorController } from './controller.cjs';
|
|
7
|
+
import type { PaintAgentTool } from './hosted.cjs';
|
|
8
|
+
export declare const EVOLUTION_MUTATION_SCHEMA: {
|
|
9
|
+
readonly type: "object";
|
|
10
|
+
readonly description: "How strongly each part of a stroke genome mutates (each 0..1; 0 keeps that part unchanged).";
|
|
11
|
+
readonly properties: {
|
|
12
|
+
readonly geometry: {
|
|
13
|
+
readonly type: "number";
|
|
14
|
+
readonly minimum: 0;
|
|
15
|
+
readonly maximum: 1;
|
|
16
|
+
readonly description: string;
|
|
17
|
+
};
|
|
18
|
+
readonly color: {
|
|
19
|
+
readonly type: "number";
|
|
20
|
+
readonly minimum: 0;
|
|
21
|
+
readonly maximum: 1;
|
|
22
|
+
readonly description: string;
|
|
23
|
+
};
|
|
24
|
+
readonly brush: {
|
|
25
|
+
readonly type: "number";
|
|
26
|
+
readonly minimum: 0;
|
|
27
|
+
readonly maximum: 1;
|
|
28
|
+
readonly description: string;
|
|
29
|
+
};
|
|
30
|
+
readonly seed: {
|
|
31
|
+
readonly type: "number";
|
|
32
|
+
readonly minimum: 0;
|
|
33
|
+
readonly maximum: 1;
|
|
34
|
+
readonly description: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
readonly additionalProperties: false;
|
|
38
|
+
};
|
|
39
|
+
export declare function createPaintEvolutionTools(c: PaintEditorController): PaintAgentTool[];
|
|
40
|
+
export declare const createEvolutionTools: typeof createPaintEvolutionTools;
|
|
41
|
+
export interface PaintEvolutionToolProviderOptions {
|
|
42
|
+
/** Provider id (unique per registry). Default `paint-evolution`. */
|
|
43
|
+
id?: string;
|
|
44
|
+
/** Tool-name prefix (`<namespace>__<name>`); defaults to the provider id, `''` for bare names. */
|
|
45
|
+
namespace?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Standalone tool provider for evolutionary strokes (also included in `createPaintEditorToolProvider`). */
|
|
48
|
+
export declare function createPaintEvolutionToolProvider(controller: PaintEditorController, options?: PaintEvolutionToolProviderOptions): AgentToolProvider;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for evolutionary strokes (`breed_strokes`, `breed_proposal`, `get_proposal_genome`).
|
|
3
|
+
* Accepting or dismissing bred variants reuses `accept_paint_proposal` and `reject_paint_proposal`.
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentToolProvider } from '../tools/registry.js';
|
|
6
|
+
import type { PaintEditorController } from './controller.js';
|
|
7
|
+
import type { PaintAgentTool } from './hosted.js';
|
|
8
|
+
export declare const EVOLUTION_MUTATION_SCHEMA: {
|
|
9
|
+
readonly type: "object";
|
|
10
|
+
readonly description: "How strongly each part of a stroke genome mutates (each 0..1; 0 keeps that part unchanged).";
|
|
11
|
+
readonly properties: {
|
|
12
|
+
readonly geometry: {
|
|
13
|
+
readonly type: "number";
|
|
14
|
+
readonly minimum: 0;
|
|
15
|
+
readonly maximum: 1;
|
|
16
|
+
readonly description: string;
|
|
17
|
+
};
|
|
18
|
+
readonly color: {
|
|
19
|
+
readonly type: "number";
|
|
20
|
+
readonly minimum: 0;
|
|
21
|
+
readonly maximum: 1;
|
|
22
|
+
readonly description: string;
|
|
23
|
+
};
|
|
24
|
+
readonly brush: {
|
|
25
|
+
readonly type: "number";
|
|
26
|
+
readonly minimum: 0;
|
|
27
|
+
readonly maximum: 1;
|
|
28
|
+
readonly description: string;
|
|
29
|
+
};
|
|
30
|
+
readonly seed: {
|
|
31
|
+
readonly type: "number";
|
|
32
|
+
readonly minimum: 0;
|
|
33
|
+
readonly maximum: 1;
|
|
34
|
+
readonly description: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
readonly additionalProperties: false;
|
|
38
|
+
};
|
|
39
|
+
export declare function createPaintEvolutionTools(c: PaintEditorController): PaintAgentTool[];
|
|
40
|
+
export declare const createEvolutionTools: typeof createPaintEvolutionTools;
|
|
41
|
+
export interface PaintEvolutionToolProviderOptions {
|
|
42
|
+
/** Provider id (unique per registry). Default `paint-evolution`. */
|
|
43
|
+
id?: string;
|
|
44
|
+
/** Tool-name prefix (`<namespace>__<name>`); defaults to the provider id, `''` for bare names. */
|
|
45
|
+
namespace?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Standalone tool provider for evolutionary strokes (also included in `createPaintEditorToolProvider`). */
|
|
48
|
+
export declare function createPaintEvolutionToolProvider(controller: PaintEditorController, options?: PaintEvolutionToolProviderOptions): AgentToolProvider;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evolutionary strokes: breed and mutate stroke variants (`RecordedStroke` genomes).
|
|
3
|
+
*
|
|
4
|
+
* - **Geometry mutation**: reuses `StrokeVariation` / `varyStroke` for whole-stroke affine drift
|
|
5
|
+
* (move, scale, rotate, pressure scale) plus seeded, smoothed point jitter along the path.
|
|
6
|
+
* - **Colour drift**: perceptual drift in OKLCH lightness, chroma and hue, gamut-mapped to sRGB.
|
|
7
|
+
* - **Brush facet drift**: drifts numeric brush facets within their schema ranges (`BRUSH_JSON_SCHEMA`)
|
|
8
|
+
* and resolves back to an engine `PaintBrush`.
|
|
9
|
+
* - **Seed reroll**: deterministic reroll of the stroke's dab/particle/bristle seed.
|
|
10
|
+
* - **Crossover**: resamples two parent stroke paths to a common point count, blends their points
|
|
11
|
+
* and colours in OKLab/OKLCH, and mixes their brush facets.
|
|
12
|
+
*/
|
|
13
|
+
import type { RasterRect } from '../raster/surface.cjs';
|
|
14
|
+
import type { PaintBrush } from './brushes.cjs';
|
|
15
|
+
import type { PaintProposal } from './collaboration.cjs';
|
|
16
|
+
import type { PaintEditorController, PixelImage } from './controller.cjs';
|
|
17
|
+
import type { PenPoint } from './engine.cjs';
|
|
18
|
+
import { strokeToJSON, type RecordedStroke, type StrokeVariation } from './strokes.cjs';
|
|
19
|
+
export type RecordedStrokeJSON = ReturnType<typeof strokeToJSON>;
|
|
20
|
+
/** How strongly each part of a stroke genome mutates (`0..1`; `0` keeps that part unchanged). */
|
|
21
|
+
export interface StrokeMutationRates {
|
|
22
|
+
/** Path variation and smoothed point jitter, 0..1 (default 0.35). */
|
|
23
|
+
geometry?: number;
|
|
24
|
+
/** Colour drift in OKLCH lightness, chroma and hue, 0..1 (default 0.35). */
|
|
25
|
+
color?: number;
|
|
26
|
+
/** Brush facet drift within schema bounds, 0..1 (default 0.35). */
|
|
27
|
+
brush?: number;
|
|
28
|
+
/** Seed reroll rate, 0..1 (default 0.5; 0 keeps the stroke seed). */
|
|
29
|
+
seed?: number;
|
|
30
|
+
}
|
|
31
|
+
export type EvolutionMutationRates = StrokeMutationRates;
|
|
32
|
+
export interface ResolvedMutationRates {
|
|
33
|
+
geometry: number;
|
|
34
|
+
color: number;
|
|
35
|
+
brush: number;
|
|
36
|
+
seed: number;
|
|
37
|
+
}
|
|
38
|
+
export declare const DEFAULT_MUTATION_RATES: ResolvedMutationRates;
|
|
39
|
+
/** Validates and fills defaults for mutation rates (`0..1`). */
|
|
40
|
+
export declare function normalizeMutationRates(rates?: StrokeMutationRates): ResolvedMutationRates;
|
|
41
|
+
/** Numeric brush facet descriptor with its schema range and drift span. */
|
|
42
|
+
export interface EvolutionBrushFacet {
|
|
43
|
+
/** Dot-path in the facet `Brush`. */
|
|
44
|
+
facet: string;
|
|
45
|
+
/** Dot-path in the resolved `PaintBrush`. */
|
|
46
|
+
engine: string;
|
|
47
|
+
/** Engines that read this facet. */
|
|
48
|
+
engines: readonly PaintBrush['engine'][];
|
|
49
|
+
/** Minimum schema value. */
|
|
50
|
+
min: number;
|
|
51
|
+
/** Maximum schema value. */
|
|
52
|
+
max: number;
|
|
53
|
+
/** Maximum drift at `mutation.brush = 1` (relative fraction when `relative` is true, else additive). */
|
|
54
|
+
span: number;
|
|
55
|
+
/** Inverse of rounding step (`1`, `10`, `100`). */
|
|
56
|
+
scale: number;
|
|
57
|
+
/** True when `span` scales the current value multiplicatively. */
|
|
58
|
+
relative?: boolean;
|
|
59
|
+
/** Optional `tip.shape` filter. */
|
|
60
|
+
shapes?: readonly string[];
|
|
61
|
+
/** Optional `marks.kind` filter. */
|
|
62
|
+
marks?: readonly string[];
|
|
63
|
+
}
|
|
64
|
+
/** Ordered table of numeric brush facets drifted and crossed over within their schema ranges. */
|
|
65
|
+
export declare const EVOLUTION_BRUSH_FACETS: readonly EvolutionBrushFacet[];
|
|
66
|
+
/**
|
|
67
|
+
* Seeded, smoothed point jitter along a stroke path: combines two harmonic waves with a 3-point
|
|
68
|
+
* smoothed random displacement so mutated paths stay fluid rather than jagged.
|
|
69
|
+
*/
|
|
70
|
+
export declare function jitterStrokePoints(points: readonly PenPoint[], amount: number, seed: number): PenPoint[];
|
|
71
|
+
/** Whole-stroke `StrokeVariation` derived from a seed and geometry mutation rate (`0..1`). */
|
|
72
|
+
export declare function seededStrokeVariation(amount: number, seed: number, index?: number): StrokeVariation;
|
|
73
|
+
/**
|
|
74
|
+
* Drifts a `#rrggbb` colour in OKLCH lightness (±0.22), chroma (±0.10) and hue (±90°) scaled by
|
|
75
|
+
* `amount` (`0..1`), reducing chroma when needed to stay inside the sRGB gamut.
|
|
76
|
+
*/
|
|
77
|
+
export declare function driftColorOklch(hex: string, amount: number, seed: number, index?: number): string;
|
|
78
|
+
/** Mixes two `#rrggbb` colours perceptually in OKLab/OKLCH at weight `t` (`0..1`). */
|
|
79
|
+
export declare function mixColorOklch(hexA: string, hexB: string, t: number): string;
|
|
80
|
+
/**
|
|
81
|
+
* Drifts a brush's numeric facets within their schema ranges (`EVOLUTION_BRUSH_FACETS`), keeping
|
|
82
|
+
* the brush compatible with live strokes (`liveStrokeRefusal`).
|
|
83
|
+
*/
|
|
84
|
+
export declare function driftBrushFacets(brush: PaintBrush, amount: number, seed: number, index?: number): PaintBrush;
|
|
85
|
+
/** Rerolls a stroke seed deterministically when `amount > 0`; keeps `strokeSeed` when `amount <= 0`. */
|
|
86
|
+
export declare function rerollStrokeSeed(strokeSeed: number, amount: number, seed: number, index?: number): number;
|
|
87
|
+
/** Resamples a stroke's points by arc length to `count` evenly spaced samples. */
|
|
88
|
+
export declare function resampleStrokePoints(points: readonly PenPoint[], count: number): PenPoint[];
|
|
89
|
+
/** Mixes two brushes by blending their applicable numeric facets onto a dominant parent's skeleton. */
|
|
90
|
+
export declare function crossoverBrushes(brushA: PaintBrush, brushB: PaintBrush, seed: number, index?: number): PaintBrush;
|
|
91
|
+
/**
|
|
92
|
+
* Crosses two parent strokes over: resamples their points to a common count, blends positions and
|
|
93
|
+
* pressures, mixes their colours in OKLab/OKLCH, mixes their brush facets and combines their seeds.
|
|
94
|
+
*/
|
|
95
|
+
export declare function crossoverStrokes(a: RecordedStroke, b: RecordedStroke, seed: number, index?: number): RecordedStroke;
|
|
96
|
+
/**
|
|
97
|
+
* Mutates one stroke genome with `rates` (`geometry`, `color`, `brush`, `seed`). When `origin` and
|
|
98
|
+
* `variation` are given (for multi-stroke motifs), whole-stroke affine drift uses them so strokes
|
|
99
|
+
* in the same genome move and turn together while each stroke's path jitters on its own.
|
|
100
|
+
*/
|
|
101
|
+
export declare function mutateStroke(stroke: RecordedStroke, rates: strokeMutationInput, seed: number, index?: number, group?: {
|
|
102
|
+
origin: {
|
|
103
|
+
x: number;
|
|
104
|
+
y: number;
|
|
105
|
+
};
|
|
106
|
+
variation: StrokeVariation;
|
|
107
|
+
}): RecordedStroke;
|
|
108
|
+
type strokeMutationInput = StrokeMutationRates | undefined;
|
|
109
|
+
export interface StrokeEvolutionChanges {
|
|
110
|
+
geometry: boolean;
|
|
111
|
+
colors: Array<{
|
|
112
|
+
from: string;
|
|
113
|
+
to: string;
|
|
114
|
+
}>;
|
|
115
|
+
facets: Record<string, {
|
|
116
|
+
from: number;
|
|
117
|
+
to: number;
|
|
118
|
+
}>;
|
|
119
|
+
seedChanged: boolean;
|
|
120
|
+
crossover: boolean;
|
|
121
|
+
}
|
|
122
|
+
/** Summarises what changed between a parent stroke genome and a bred child genome. */
|
|
123
|
+
export declare function describeGenomeDiff(parents: readonly RecordedStroke[], children: readonly RecordedStroke[], options?: {
|
|
124
|
+
crossover?: boolean;
|
|
125
|
+
}): {
|
|
126
|
+
diff: string;
|
|
127
|
+
changes: StrokeEvolutionChanges;
|
|
128
|
+
};
|
|
129
|
+
/** Mutates a multi-stroke genome at `variantSeed`. */
|
|
130
|
+
export declare function mutateGenome(strokes: readonly RecordedStroke[], rates: StrokeMutationRates | undefined, variantSeed: number): RecordedStroke[];
|
|
131
|
+
/** Crosses two stroke genomes over and mutates the offspring at `variantSeed`. */
|
|
132
|
+
export declare function crossoverGenomes(genomeA: readonly RecordedStroke[], genomeB: readonly RecordedStroke[], rates: StrokeMutationRates | undefined, variantSeed: number): RecordedStroke[];
|
|
133
|
+
/** Checks that every stroke in a genome can be bred and previewed (refuses brushes `liveStrokeRefusal` rejects). */
|
|
134
|
+
export declare function checkEvolutionStrokes(strokes: readonly RecordedStroke[]): void;
|
|
135
|
+
export interface BredProposalSummary {
|
|
136
|
+
proposalId: string;
|
|
137
|
+
title: string;
|
|
138
|
+
seed: number;
|
|
139
|
+
bounds: RasterRect | null;
|
|
140
|
+
diff: string;
|
|
141
|
+
changes: StrokeEvolutionChanges;
|
|
142
|
+
}
|
|
143
|
+
export interface BreedStrokesResult {
|
|
144
|
+
proposalIds: string[];
|
|
145
|
+
proposals: BredProposalSummary[];
|
|
146
|
+
}
|
|
147
|
+
export interface ProposalGenomeResult {
|
|
148
|
+
proposalId: string;
|
|
149
|
+
title: string;
|
|
150
|
+
bounds: RasterRect | null;
|
|
151
|
+
strokes: RecordedStrokeJSON[];
|
|
152
|
+
}
|
|
153
|
+
/** Extracts the stroke genome of a pending `PaintProposal`, or returns `[]` when it has none. */
|
|
154
|
+
export declare function proposalGenomeStrokes(first: PaintEditorController | PaintProposal, second?: PaintProposal): RecordedStroke[];
|
|
155
|
+
/**
|
|
156
|
+
* Renders a contact sheet (`replay.ts:contactSheet`) of pending proposals' ghosts composited over
|
|
157
|
+
* the current canvas, for grid export.
|
|
158
|
+
*/
|
|
159
|
+
export declare function renderProposalContactSheet(controller: PaintEditorController, proposals: readonly PaintProposal[], options?: {
|
|
160
|
+
columns?: number;
|
|
161
|
+
cell?: number;
|
|
162
|
+
paper?: boolean;
|
|
163
|
+
}): PixelImage;
|
|
164
|
+
/** Encodes `renderProposalContactSheet` as a PNG byte array and base64 string. */
|
|
165
|
+
export declare function exportProposalContactSheetPng(controller: PaintEditorController, proposals: readonly PaintProposal[], options?: {
|
|
166
|
+
columns?: number;
|
|
167
|
+
cell?: number;
|
|
168
|
+
paper?: boolean;
|
|
169
|
+
}): {
|
|
170
|
+
width: number;
|
|
171
|
+
height: number;
|
|
172
|
+
bytes: Uint8Array;
|
|
173
|
+
base64: string;
|
|
174
|
+
};
|
|
175
|
+
export { strokeToJSON };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evolutionary strokes: breed and mutate stroke variants (`RecordedStroke` genomes).
|
|
3
|
+
*
|
|
4
|
+
* - **Geometry mutation**: reuses `StrokeVariation` / `varyStroke` for whole-stroke affine drift
|
|
5
|
+
* (move, scale, rotate, pressure scale) plus seeded, smoothed point jitter along the path.
|
|
6
|
+
* - **Colour drift**: perceptual drift in OKLCH lightness, chroma and hue, gamut-mapped to sRGB.
|
|
7
|
+
* - **Brush facet drift**: drifts numeric brush facets within their schema ranges (`BRUSH_JSON_SCHEMA`)
|
|
8
|
+
* and resolves back to an engine `PaintBrush`.
|
|
9
|
+
* - **Seed reroll**: deterministic reroll of the stroke's dab/particle/bristle seed.
|
|
10
|
+
* - **Crossover**: resamples two parent stroke paths to a common point count, blends their points
|
|
11
|
+
* and colours in OKLab/OKLCH, and mixes their brush facets.
|
|
12
|
+
*/
|
|
13
|
+
import type { RasterRect } from '../raster/surface.js';
|
|
14
|
+
import type { PaintBrush } from './brushes.js';
|
|
15
|
+
import type { PaintProposal } from './collaboration.js';
|
|
16
|
+
import type { PaintEditorController, PixelImage } from './controller.js';
|
|
17
|
+
import type { PenPoint } from './engine.js';
|
|
18
|
+
import { strokeToJSON, type RecordedStroke, type StrokeVariation } from './strokes.js';
|
|
19
|
+
export type RecordedStrokeJSON = ReturnType<typeof strokeToJSON>;
|
|
20
|
+
/** How strongly each part of a stroke genome mutates (`0..1`; `0` keeps that part unchanged). */
|
|
21
|
+
export interface StrokeMutationRates {
|
|
22
|
+
/** Path variation and smoothed point jitter, 0..1 (default 0.35). */
|
|
23
|
+
geometry?: number;
|
|
24
|
+
/** Colour drift in OKLCH lightness, chroma and hue, 0..1 (default 0.35). */
|
|
25
|
+
color?: number;
|
|
26
|
+
/** Brush facet drift within schema bounds, 0..1 (default 0.35). */
|
|
27
|
+
brush?: number;
|
|
28
|
+
/** Seed reroll rate, 0..1 (default 0.5; 0 keeps the stroke seed). */
|
|
29
|
+
seed?: number;
|
|
30
|
+
}
|
|
31
|
+
export type EvolutionMutationRates = StrokeMutationRates;
|
|
32
|
+
export interface ResolvedMutationRates {
|
|
33
|
+
geometry: number;
|
|
34
|
+
color: number;
|
|
35
|
+
brush: number;
|
|
36
|
+
seed: number;
|
|
37
|
+
}
|
|
38
|
+
export declare const DEFAULT_MUTATION_RATES: ResolvedMutationRates;
|
|
39
|
+
/** Validates and fills defaults for mutation rates (`0..1`). */
|
|
40
|
+
export declare function normalizeMutationRates(rates?: StrokeMutationRates): ResolvedMutationRates;
|
|
41
|
+
/** Numeric brush facet descriptor with its schema range and drift span. */
|
|
42
|
+
export interface EvolutionBrushFacet {
|
|
43
|
+
/** Dot-path in the facet `Brush`. */
|
|
44
|
+
facet: string;
|
|
45
|
+
/** Dot-path in the resolved `PaintBrush`. */
|
|
46
|
+
engine: string;
|
|
47
|
+
/** Engines that read this facet. */
|
|
48
|
+
engines: readonly PaintBrush['engine'][];
|
|
49
|
+
/** Minimum schema value. */
|
|
50
|
+
min: number;
|
|
51
|
+
/** Maximum schema value. */
|
|
52
|
+
max: number;
|
|
53
|
+
/** Maximum drift at `mutation.brush = 1` (relative fraction when `relative` is true, else additive). */
|
|
54
|
+
span: number;
|
|
55
|
+
/** Inverse of rounding step (`1`, `10`, `100`). */
|
|
56
|
+
scale: number;
|
|
57
|
+
/** True when `span` scales the current value multiplicatively. */
|
|
58
|
+
relative?: boolean;
|
|
59
|
+
/** Optional `tip.shape` filter. */
|
|
60
|
+
shapes?: readonly string[];
|
|
61
|
+
/** Optional `marks.kind` filter. */
|
|
62
|
+
marks?: readonly string[];
|
|
63
|
+
}
|
|
64
|
+
/** Ordered table of numeric brush facets drifted and crossed over within their schema ranges. */
|
|
65
|
+
export declare const EVOLUTION_BRUSH_FACETS: readonly EvolutionBrushFacet[];
|
|
66
|
+
/**
|
|
67
|
+
* Seeded, smoothed point jitter along a stroke path: combines two harmonic waves with a 3-point
|
|
68
|
+
* smoothed random displacement so mutated paths stay fluid rather than jagged.
|
|
69
|
+
*/
|
|
70
|
+
export declare function jitterStrokePoints(points: readonly PenPoint[], amount: number, seed: number): PenPoint[];
|
|
71
|
+
/** Whole-stroke `StrokeVariation` derived from a seed and geometry mutation rate (`0..1`). */
|
|
72
|
+
export declare function seededStrokeVariation(amount: number, seed: number, index?: number): StrokeVariation;
|
|
73
|
+
/**
|
|
74
|
+
* Drifts a `#rrggbb` colour in OKLCH lightness (±0.22), chroma (±0.10) and hue (±90°) scaled by
|
|
75
|
+
* `amount` (`0..1`), reducing chroma when needed to stay inside the sRGB gamut.
|
|
76
|
+
*/
|
|
77
|
+
export declare function driftColorOklch(hex: string, amount: number, seed: number, index?: number): string;
|
|
78
|
+
/** Mixes two `#rrggbb` colours perceptually in OKLab/OKLCH at weight `t` (`0..1`). */
|
|
79
|
+
export declare function mixColorOklch(hexA: string, hexB: string, t: number): string;
|
|
80
|
+
/**
|
|
81
|
+
* Drifts a brush's numeric facets within their schema ranges (`EVOLUTION_BRUSH_FACETS`), keeping
|
|
82
|
+
* the brush compatible with live strokes (`liveStrokeRefusal`).
|
|
83
|
+
*/
|
|
84
|
+
export declare function driftBrushFacets(brush: PaintBrush, amount: number, seed: number, index?: number): PaintBrush;
|
|
85
|
+
/** Rerolls a stroke seed deterministically when `amount > 0`; keeps `strokeSeed` when `amount <= 0`. */
|
|
86
|
+
export declare function rerollStrokeSeed(strokeSeed: number, amount: number, seed: number, index?: number): number;
|
|
87
|
+
/** Resamples a stroke's points by arc length to `count` evenly spaced samples. */
|
|
88
|
+
export declare function resampleStrokePoints(points: readonly PenPoint[], count: number): PenPoint[];
|
|
89
|
+
/** Mixes two brushes by blending their applicable numeric facets onto a dominant parent's skeleton. */
|
|
90
|
+
export declare function crossoverBrushes(brushA: PaintBrush, brushB: PaintBrush, seed: number, index?: number): PaintBrush;
|
|
91
|
+
/**
|
|
92
|
+
* Crosses two parent strokes over: resamples their points to a common count, blends positions and
|
|
93
|
+
* pressures, mixes their colours in OKLab/OKLCH, mixes their brush facets and combines their seeds.
|
|
94
|
+
*/
|
|
95
|
+
export declare function crossoverStrokes(a: RecordedStroke, b: RecordedStroke, seed: number, index?: number): RecordedStroke;
|
|
96
|
+
/**
|
|
97
|
+
* Mutates one stroke genome with `rates` (`geometry`, `color`, `brush`, `seed`). When `origin` and
|
|
98
|
+
* `variation` are given (for multi-stroke motifs), whole-stroke affine drift uses them so strokes
|
|
99
|
+
* in the same genome move and turn together while each stroke's path jitters on its own.
|
|
100
|
+
*/
|
|
101
|
+
export declare function mutateStroke(stroke: RecordedStroke, rates: strokeMutationInput, seed: number, index?: number, group?: {
|
|
102
|
+
origin: {
|
|
103
|
+
x: number;
|
|
104
|
+
y: number;
|
|
105
|
+
};
|
|
106
|
+
variation: StrokeVariation;
|
|
107
|
+
}): RecordedStroke;
|
|
108
|
+
type strokeMutationInput = StrokeMutationRates | undefined;
|
|
109
|
+
export interface StrokeEvolutionChanges {
|
|
110
|
+
geometry: boolean;
|
|
111
|
+
colors: Array<{
|
|
112
|
+
from: string;
|
|
113
|
+
to: string;
|
|
114
|
+
}>;
|
|
115
|
+
facets: Record<string, {
|
|
116
|
+
from: number;
|
|
117
|
+
to: number;
|
|
118
|
+
}>;
|
|
119
|
+
seedChanged: boolean;
|
|
120
|
+
crossover: boolean;
|
|
121
|
+
}
|
|
122
|
+
/** Summarises what changed between a parent stroke genome and a bred child genome. */
|
|
123
|
+
export declare function describeGenomeDiff(parents: readonly RecordedStroke[], children: readonly RecordedStroke[], options?: {
|
|
124
|
+
crossover?: boolean;
|
|
125
|
+
}): {
|
|
126
|
+
diff: string;
|
|
127
|
+
changes: StrokeEvolutionChanges;
|
|
128
|
+
};
|
|
129
|
+
/** Mutates a multi-stroke genome at `variantSeed`. */
|
|
130
|
+
export declare function mutateGenome(strokes: readonly RecordedStroke[], rates: StrokeMutationRates | undefined, variantSeed: number): RecordedStroke[];
|
|
131
|
+
/** Crosses two stroke genomes over and mutates the offspring at `variantSeed`. */
|
|
132
|
+
export declare function crossoverGenomes(genomeA: readonly RecordedStroke[], genomeB: readonly RecordedStroke[], rates: StrokeMutationRates | undefined, variantSeed: number): RecordedStroke[];
|
|
133
|
+
/** Checks that every stroke in a genome can be bred and previewed (refuses brushes `liveStrokeRefusal` rejects). */
|
|
134
|
+
export declare function checkEvolutionStrokes(strokes: readonly RecordedStroke[]): void;
|
|
135
|
+
export interface BredProposalSummary {
|
|
136
|
+
proposalId: string;
|
|
137
|
+
title: string;
|
|
138
|
+
seed: number;
|
|
139
|
+
bounds: RasterRect | null;
|
|
140
|
+
diff: string;
|
|
141
|
+
changes: StrokeEvolutionChanges;
|
|
142
|
+
}
|
|
143
|
+
export interface BreedStrokesResult {
|
|
144
|
+
proposalIds: string[];
|
|
145
|
+
proposals: BredProposalSummary[];
|
|
146
|
+
}
|
|
147
|
+
export interface ProposalGenomeResult {
|
|
148
|
+
proposalId: string;
|
|
149
|
+
title: string;
|
|
150
|
+
bounds: RasterRect | null;
|
|
151
|
+
strokes: RecordedStrokeJSON[];
|
|
152
|
+
}
|
|
153
|
+
/** Extracts the stroke genome of a pending `PaintProposal`, or returns `[]` when it has none. */
|
|
154
|
+
export declare function proposalGenomeStrokes(first: PaintEditorController | PaintProposal, second?: PaintProposal): RecordedStroke[];
|
|
155
|
+
/**
|
|
156
|
+
* Renders a contact sheet (`replay.ts:contactSheet`) of pending proposals' ghosts composited over
|
|
157
|
+
* the current canvas, for grid export.
|
|
158
|
+
*/
|
|
159
|
+
export declare function renderProposalContactSheet(controller: PaintEditorController, proposals: readonly PaintProposal[], options?: {
|
|
160
|
+
columns?: number;
|
|
161
|
+
cell?: number;
|
|
162
|
+
paper?: boolean;
|
|
163
|
+
}): PixelImage;
|
|
164
|
+
/** Encodes `renderProposalContactSheet` as a PNG byte array and base64 string. */
|
|
165
|
+
export declare function exportProposalContactSheetPng(controller: PaintEditorController, proposals: readonly PaintProposal[], options?: {
|
|
166
|
+
columns?: number;
|
|
167
|
+
cell?: number;
|
|
168
|
+
paper?: boolean;
|
|
169
|
+
}): {
|
|
170
|
+
width: number;
|
|
171
|
+
height: number;
|
|
172
|
+
bytes: Uint8Array;
|
|
173
|
+
base64: string;
|
|
174
|
+
};
|
|
175
|
+
export { strokeToJSON };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart inks: UV-fluorescent ink (`doc.fluor[layerId]` + `uvLight`) and thermochromic ink
|
|
3
|
+
* (`doc.thermo[layerId]` + `doc.heat`).
|
|
4
|
+
*
|
|
5
|
+
* - **Fluorescent ink**: a per-layer 4-channel RGBA surface (`[R, G, B, intensity]`) in layer
|
|
6
|
+
* space, painted alongside strokes when `brush.fluorescence.amount > 0`. With
|
|
7
|
+
* `brush.fluorescence.invisible: true`, no daylight pigment is laid onto the layer's normal
|
|
8
|
+
* surface, so the mark stays invisible under normal light. When the virtual UV blacklight
|
|
9
|
+
* (`uvLight.on`) is switched on, normal layers dim to `uvLight.ambient` and fluorescent pixels
|
|
10
|
+
* emit their colour and cast a Linear Dodge spill halo (reusing `computeSpill` from `./light`).
|
|
11
|
+
* - **Thermochromic ink**: a per-layer 4-channel RGBA surface (`[hotR, hotG, hotB, thresholdByte]`)
|
|
12
|
+
* in layer space, painted when `brush.thermochromic.hotColor` is set. A document-level coarse
|
|
13
|
+
* heat field (`HEAT_SCALE = 4`, 1/4 canvas resolution) stores local temperature in `0..1`,
|
|
14
|
+
* painted by `paintHeatField` and stepped with 5-point Laplacian diffusion + Newtonian cooling
|
|
15
|
+
* by `advanceHeatField`. At render time, thermochromic pixels blend smoothly from their cold
|
|
16
|
+
* paint colour to `hotColor` around `threshold` based on bilinearly sampled temperature, and
|
|
17
|
+
* tiles heated past `HEAT_DRY_THRESHOLD` dry any wet paint on them.
|
|
18
|
+
*/
|
|
19
|
+
import { TiledSurface, type RasterRect } from '../raster/surface.cjs';
|
|
20
|
+
import { type PaintBrush } from './brushes.cjs';
|
|
21
|
+
import { type PaperSettings } from './paper.cjs';
|
|
22
|
+
/** View / document UV blacklight setting. */
|
|
23
|
+
export interface UvLightSettings {
|
|
24
|
+
/** Whether the UV blacklight is switched on (default false). */
|
|
25
|
+
on: boolean;
|
|
26
|
+
/** Emission and halo strength under UV, 0..2 (default 1). */
|
|
27
|
+
strength: number;
|
|
28
|
+
/** How much normal daylight colour remains visible when UV is on, 0 (pitch dark) .. 1 (default 0.15). */
|
|
29
|
+
ambient: number;
|
|
30
|
+
}
|
|
31
|
+
export declare const DEFAULT_UV_LIGHT: Readonly<UvLightSettings>;
|
|
32
|
+
export declare function normalizeUvLight(raw?: Partial<UvLightSettings>, base?: UvLightSettings): UvLightSettings;
|
|
33
|
+
export declare function uvLightKey(uv: UvLightSettings): string;
|
|
34
|
+
/** The paper dimmed to `uv.ambient` while the UV blacklight is on (cached by paper reference). */
|
|
35
|
+
export declare function uvPaper(paper: PaperSettings, uv: UvLightSettings): PaperSettings;
|
|
36
|
+
export declare function emptyFluor(): TiledSurface;
|
|
37
|
+
export declare function emptyThermo(): TiledSurface;
|
|
38
|
+
/**
|
|
39
|
+
* Twin brush that writes or moves the per-layer 4-channel fluorescence surface (`doc.fluor[id]`).
|
|
40
|
+
* When `brush.fluorescence.amount > 0`, it lays the stroke's colour scaled by `fluorescence.amount`;
|
|
41
|
+
* erasers, smudges and blenders act on the existing fluorescence; plain opaque paint dims it.
|
|
42
|
+
*/
|
|
43
|
+
export declare function fluorTwinBrush(brush: PaintBrush): PaintBrush;
|
|
44
|
+
/**
|
|
45
|
+
* Twin brush that writes or moves the per-layer 4-channel thermochromic surface (`doc.thermo[id]`).
|
|
46
|
+
*/
|
|
47
|
+
export declare function thermoTwinBrush(brush: PaintBrush): PaintBrush;
|
|
48
|
+
/**
|
|
49
|
+
* Encodes `threshold` (`0.05..0.95`) into channel 3 (`1..255`) of a thermochromic surface after a
|
|
50
|
+
* twin stroke painted `hotColor` with coverage in channel 3. Existing thermochromic pixels blend
|
|
51
|
+
* smoothly with the new `hotColor` and `threshold` by the twin's coverage.
|
|
52
|
+
*/
|
|
53
|
+
export declare function finalizeThermoStroke(twinOut: TiledSurface, before: TiledSurface, hotRgb: readonly [number, number, number], threshold: number): TiledSurface;
|
|
54
|
+
/** Scales the alpha channel of a 4-channel RGBA surface (`fluor`) by `k` (0..1). */
|
|
55
|
+
export declare function scaleFluor(surface: TiledSurface, k: number): TiledSurface;
|
|
56
|
+
/** Merges two 4-channel surfaces (`above` over `below`) when merging layers down. */
|
|
57
|
+
export declare function mergeFourChannel(below: TiledSurface | undefined, above: TiledSurface | undefined): TiledSurface | null;
|
|
58
|
+
/** Computes the UV spill halo for a layer's `fluor` surface, reusing `computeSpill` from `./light`. */
|
|
59
|
+
export declare function computeUvSpill(fluor: TiledSurface, strength: number): TiledSurface | null;
|
|
60
|
+
/**
|
|
61
|
+
* Tile cache for UV blacklight rendering on one layer: dims daylight pixels to `uvLight.ambient`
|
|
62
|
+
* and adds fluorescent emission from `doc.fluor[id]` (even where daylight alpha is 0 for invisible ink).
|
|
63
|
+
*/
|
|
64
|
+
export declare class UvCache {
|
|
65
|
+
private readonly tiles;
|
|
66
|
+
private spillCache;
|
|
67
|
+
render(color: TiledSurface, fluor: TiledSurface | undefined, uv: UvLightSettings): TiledSurface;
|
|
68
|
+
spill(fluor: TiledSurface, uv: UvLightSettings): TiledSurface | null;
|
|
69
|
+
}
|
|
70
|
+
/** Coarse grid scale: 1 heat cell per 4×4 canvas pixels. */
|
|
71
|
+
export declare const HEAT_SCALE = 4;
|
|
72
|
+
/** Explicit 2D diffusion rate per step (≤ 0.25 for stability). */
|
|
73
|
+
export declare const HEAT_DIFFUSION = 0.18;
|
|
74
|
+
/** Newtonian cooling fraction per step. */
|
|
75
|
+
export declare const HEAT_COOLING = 0.03;
|
|
76
|
+
/** Temperature above which a heated cell dries wet paint. */
|
|
77
|
+
export declare const HEAT_DRY_THRESHOLD = 0.5;
|
|
78
|
+
export interface HeatField {
|
|
79
|
+
width: number;
|
|
80
|
+
height: number;
|
|
81
|
+
gridWidth: number;
|
|
82
|
+
gridHeight: number;
|
|
83
|
+
/** Row-major temperatures in 0..1 (`gridWidth * gridHeight`). */
|
|
84
|
+
cells: Float64Array;
|
|
85
|
+
max: number;
|
|
86
|
+
revision: number;
|
|
87
|
+
}
|
|
88
|
+
export interface HeatSample {
|
|
89
|
+
x: number;
|
|
90
|
+
y: number;
|
|
91
|
+
temperature: number;
|
|
92
|
+
}
|
|
93
|
+
export declare function createHeatField(width: number, height: number): HeatField;
|
|
94
|
+
export declare function cloneHeatField(field: HeatField): HeatField;
|
|
95
|
+
export interface HeatStats {
|
|
96
|
+
max: number;
|
|
97
|
+
mean: number;
|
|
98
|
+
hotCells: number;
|
|
99
|
+
bounds: RasterRect | null;
|
|
100
|
+
}
|
|
101
|
+
export declare function heatStats(field: HeatField | undefined): HeatStats;
|
|
102
|
+
/** Bounding document-space rectangle of all coarse cells with temperature ≥ `threshold`, or `null`. */
|
|
103
|
+
export declare function hotCellsBounds(field: HeatField, threshold?: number): RasterRect | null;
|
|
104
|
+
/**
|
|
105
|
+
* Paints heat (or cools when `temperature` is below current cell heat) along `points` with `radius`
|
|
106
|
+
* in document pixels. Returns the affected document-space bounding box and updated field statistics.
|
|
107
|
+
*/
|
|
108
|
+
export declare function paintHeatField(field: HeatField, points: ReadonlyArray<{
|
|
109
|
+
x: number;
|
|
110
|
+
y: number;
|
|
111
|
+
}>, radius?: number, temperature?: number): {
|
|
112
|
+
bounds: RasterRect;
|
|
113
|
+
stats: HeatStats;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Advances the heat field by `steps` iterations of 5-point Laplacian diffusion and Newtonian cooling.
|
|
117
|
+
*/
|
|
118
|
+
export declare function advanceHeatField(field: HeatField, steps?: number): HeatStats;
|
|
119
|
+
/** Clears the heat field to 0 everywhere. */
|
|
120
|
+
export declare function clearHeatField(field: HeatField): boolean;
|
|
121
|
+
/** Bilinearly samples temperature (0..1) at document coordinates `(x, y)`. */
|
|
122
|
+
export declare function sampleHeatAt(field: HeatField, x: number, y: number): number;
|
|
123
|
+
/** Shifts and resizes a heat field when `extendCanvas` shifts the document by `(dx, dy)`. */
|
|
124
|
+
export declare function shiftHeatField(field: HeatField, dx: number, dy: number, newWidth: number, newHeight: number): HeatField;
|
|
125
|
+
/**
|
|
126
|
+
* Tile cache for thermochromic colour shifting on one layer: blends cold pixels toward `hotColor`
|
|
127
|
+
* around `threshold` where the coarse heat field is warm.
|
|
128
|
+
*/
|
|
129
|
+
export declare class ThermoCache {
|
|
130
|
+
private readonly tiles;
|
|
131
|
+
render(color: TiledSurface, thermo: TiledSurface | undefined, offset: {
|
|
132
|
+
x: number;
|
|
133
|
+
y: number;
|
|
134
|
+
}, heat: HeatField): TiledSurface;
|
|
135
|
+
}
|
|
136
|
+
export interface SavedLayerFluor {
|
|
137
|
+
rect: RasterRect;
|
|
138
|
+
/** 4-channel RGBA PNG data URL of the layer's fluorescence. */
|
|
139
|
+
fluor: string;
|
|
140
|
+
}
|
|
141
|
+
export interface SavedLayerThermo {
|
|
142
|
+
rect: RasterRect;
|
|
143
|
+
/** 4-channel RGBA PNG data URL of the layer's thermochromic `[hotR, hotG, hotB, thresholdByte]`. */
|
|
144
|
+
thermo: string;
|
|
145
|
+
}
|
|
146
|
+
export interface SavedHeatField {
|
|
147
|
+
gridWidth: number;
|
|
148
|
+
gridHeight: number;
|
|
149
|
+
cells: number[];
|
|
150
|
+
}
|
|
151
|
+
export declare function fluorToJSON(fluor: TiledSurface | undefined): SavedLayerFluor | null;
|
|
152
|
+
export declare function fluorFromJSON(raw: unknown): TiledSurface;
|
|
153
|
+
export declare function thermoToJSON(thermo: TiledSurface | undefined): SavedLayerThermo | null;
|
|
154
|
+
export declare function thermoFromJSON(raw: unknown): TiledSurface;
|
|
155
|
+
export declare function heatToJSON(field: HeatField | undefined): SavedHeatField | null;
|
|
156
|
+
export declare function heatFromJSON(raw: unknown, width: number, height: number): HeatField | null;
|