@pixerate/editor 0.281.0 → 0.282.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 +76 -71
- package/dist/brushes/index.js +13 -8
- package/dist/brushes/schema.d.cts +1 -0
- package/dist/brushes/schema.d.ts +1 -0
- package/dist/brushes/types.d.cts +29 -3
- package/dist/brushes/types.d.ts +29 -3
- package/dist/{brushstrokeRender-EIK3625T.js → brushstrokeRender-4MA5CBW3.js} +3 -3
- package/dist/{brushstrokeRender-7HOMKZNO.cjs → brushstrokeRender-JVKVKWDA.cjs} +15 -15
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-NJDEKU5D.js → chunk-2YGYYVSG.js} +1 -1
- package/dist/{chunk-JVFGK3DK.cjs → chunk-3JUKN3RM.cjs} +76 -53
- package/dist/{chunk-HN57I7KT.js → chunk-CG3FBNXE.js} +1 -1
- package/dist/{chunk-WFSYZO5Z.cjs → chunk-DFZ4I7EZ.cjs} +1 -1
- package/dist/{chunk-LZE2QZCT.js → chunk-IHMMHZGP.js} +1 -1
- package/dist/{chunk-K4ANWBF7.cjs → chunk-IJQ2YH2M.cjs} +35 -35
- package/dist/{chunk-HRUK5TFW.cjs → chunk-IUKPQCYQ.cjs} +164 -71
- package/dist/{chunk-WCC4NXWY.cjs → chunk-JD63B33V.cjs} +86 -86
- package/dist/{chunk-NJLPW4MM.js → chunk-KV7QHPKL.js} +27 -4
- package/dist/{chunk-H3EME3S5.cjs → chunk-MRIAR5DY.cjs} +2 -2
- package/dist/{chunk-ROURHJYT.js → chunk-NEDS6DSC.js} +1 -1
- package/dist/{chunk-FKO3CY2C.js → chunk-ULPXJ3NB.js} +1 -1
- package/dist/{chunk-WZYRYYXN.cjs → chunk-UOM5S4W5.cjs} +12 -12
- package/dist/{chunk-YOM76H2V.js → chunk-VEX6YVNG.js} +1 -1
- package/dist/{chunk-MNHP3AQT.cjs → chunk-WEXWDBUF.cjs} +23 -23
- package/dist/{chunk-PPDUCZZV.js → chunk-YRGTQLDN.js} +122 -29
- package/dist/image-editor/index.cjs +788 -788
- package/dist/image-editor/index.js +4 -4
- package/dist/paint-editor/antimatter.d.cts +154 -0
- package/dist/paint-editor/antimatter.d.ts +154 -0
- package/dist/paint-editor/brush-controls.d.cts +1 -0
- package/dist/paint-editor/brush-controls.d.ts +1 -0
- package/dist/paint-editor/brush-model.d.cts +9 -5
- package/dist/paint-editor/brush-model.d.ts +9 -5
- package/dist/paint-editor/controller.d.cts +23 -0
- package/dist/paint-editor/controller.d.ts +23 -0
- package/dist/paint-editor/index.cjs +1931 -891
- package/dist/paint-editor/index.d.cts +1 -0
- package/dist/paint-editor/index.d.ts +1 -0
- package/dist/paint-editor/index.js +1098 -58
- package/dist/paint-editor/mark-settings.d.cts +30 -0
- package/dist/paint-editor/mark-settings.d.ts +30 -0
- package/dist/paint-editor/stroke.d.cts +16 -0
- package/dist/paint-editor/stroke.d.ts +16 -0
- package/dist/paint-editor/strokes.d.cts +2 -0
- package/dist/paint-editor/strokes.d.ts +2 -0
- package/dist/paint-editor/ui.d.cts +4 -2
- package/dist/paint-editor/ui.d.ts +4 -2
- package/dist/vector/index.cjs +999 -999
- package/dist/vector/index.js +4 -4
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +1 -1
- package/skills/pixerate-paint-editor/SKILL.md +8 -2
- package/skills/pixerate-paint-editor/references/antimatter.md +49 -0
- package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
parseOpenTypeFont,
|
|
9
9
|
removeAnchorsKeepingShape,
|
|
10
10
|
traceField
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-CG3FBNXE.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-2YGYYVSG.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-VEX6YVNG.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-YRGTQLDN.js";
|
|
694
694
|
import "../chunk-JL6YH5WD.js";
|
|
695
695
|
import "../chunk-RWDSSK2I.js";
|
|
696
696
|
import {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antimatter paint (`engine: 'antimatter'`, `marks.kind: 'antimatter'`): animated blasts that
|
|
3
|
+
* detonate where the brush touches paint across any visible layer, inverting colours in the core,
|
|
4
|
+
* removing alpha, burning a soot ring around the crater, denting thick relief, clearing core light,
|
|
5
|
+
* and throwing white-hot ballistic sparks on the active layer.
|
|
6
|
+
*/
|
|
7
|
+
import { type PaintGradientSource } from '../paint/gradient-paint.cjs';
|
|
8
|
+
import { TiledSurface, type RasterRect } from '../raster/surface.cjs';
|
|
9
|
+
import type { PaintBrush } from './brushes.cjs';
|
|
10
|
+
import { type EffectPaintPixels } from './effect-paint.cjs';
|
|
11
|
+
import { type PenPoint, type StrokeCopy } from './engine.cjs';
|
|
12
|
+
import { DEFAULT_ANTIMATTER, INVERT_MODES, normalizeAntimatter, type AntimatterSettings, type InvertMode } from './mark-settings.cjs';
|
|
13
|
+
import type { ThickChannels } from './thick.cjs';
|
|
14
|
+
export { DEFAULT_ANTIMATTER, INVERT_MODES, normalizeAntimatter, type AntimatterSettings, type InvertMode };
|
|
15
|
+
/** One detonation along an antimatter stroke. */
|
|
16
|
+
export interface AntimatterBlast {
|
|
17
|
+
index: number;
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
/** Blast radius in document pixels. */
|
|
21
|
+
radius: number;
|
|
22
|
+
/** Tip diameter at the dab that fired this blast. */
|
|
23
|
+
tipSize: number;
|
|
24
|
+
/** Tip opacity at the dab that fired this blast (`0..1`). */
|
|
25
|
+
tipOpacity: number;
|
|
26
|
+
/** Fuel (`0..1`) that triggered this blast. */
|
|
27
|
+
fuel: number;
|
|
28
|
+
/** Copy-specific seed for noise and sparks. */
|
|
29
|
+
seed: number;
|
|
30
|
+
/** Spark target colour (0..255 RGB). */
|
|
31
|
+
color: [number, number, number];
|
|
32
|
+
/** Light intensity (`0..1`) sparks write to `doc.light` on the active layer. */
|
|
33
|
+
lightAmount: number;
|
|
34
|
+
/** Number of sparks spawned by this blast. */
|
|
35
|
+
sparkCount: number;
|
|
36
|
+
/** Birth timestamp in ms (from `PenPoint.t` or the host clock). */
|
|
37
|
+
t: number;
|
|
38
|
+
}
|
|
39
|
+
/** Summary returned on `PaintStrokeResult.antimatter`. */
|
|
40
|
+
export interface AntimatterStats {
|
|
41
|
+
blasts: number;
|
|
42
|
+
sparks: number;
|
|
43
|
+
fuel: number;
|
|
44
|
+
layers: string[];
|
|
45
|
+
skippedLayers: string[];
|
|
46
|
+
}
|
|
47
|
+
/** One visible layer that supplies fuel to the antimatter stroke (and is edited if `editable`). */
|
|
48
|
+
export interface AntimatterTarget {
|
|
49
|
+
id: string;
|
|
50
|
+
/** True for unlocked pixel layers (not stroke, sticker or effect layers). */
|
|
51
|
+
editable: boolean;
|
|
52
|
+
lockTransparency: boolean;
|
|
53
|
+
opacity: number;
|
|
54
|
+
offset: {
|
|
55
|
+
x: number;
|
|
56
|
+
y: number;
|
|
57
|
+
};
|
|
58
|
+
/** Pre-stroke pixel surface (read-only fuel & recomposite source). */
|
|
59
|
+
base: TiledSurface;
|
|
60
|
+
/** Pre-stroke light channel (`doc.light[id]`), if any. */
|
|
61
|
+
baseLight?: TiledSurface | null;
|
|
62
|
+
/** Pre-stroke thick-paint channels (`doc.thick[id]`), if any. */
|
|
63
|
+
baseThick?: ThickChannels | null;
|
|
64
|
+
}
|
|
65
|
+
/** Per-layer output surfaces produced by `AntimatterStrokeDriver`. */
|
|
66
|
+
export interface AntimatterLayerOutput {
|
|
67
|
+
id: string;
|
|
68
|
+
surface: TiledSurface;
|
|
69
|
+
light: TiledSurface | null;
|
|
70
|
+
thick: ThickChannels | null;
|
|
71
|
+
changed: boolean;
|
|
72
|
+
}
|
|
73
|
+
export interface AntimatterStrokeInit {
|
|
74
|
+
activeLayerId: string;
|
|
75
|
+
targets: readonly AntimatterTarget[];
|
|
76
|
+
brush: PaintBrush;
|
|
77
|
+
/** Paint colour 0..255 RGBA. */
|
|
78
|
+
color: readonly [number, number, number, number];
|
|
79
|
+
seed: number;
|
|
80
|
+
copies: readonly StrokeCopy[];
|
|
81
|
+
selection?: {
|
|
82
|
+
width: number;
|
|
83
|
+
height: number;
|
|
84
|
+
data: ArrayLike<number>;
|
|
85
|
+
} | null;
|
|
86
|
+
paint?: PaintGradientSource | null;
|
|
87
|
+
effect?: EffectPaintPixels | null;
|
|
88
|
+
/** Current clock in ms for stamping blast birth times during live strokes. */
|
|
89
|
+
now?: () => number;
|
|
90
|
+
}
|
|
91
|
+
/** Smooth 2D value noise in `0..1` using only `Math.floor` and `hash2` (identical across TS and Swift). */
|
|
92
|
+
export declare function blastNoise2D(ux: number, uy: number, salt: number): number;
|
|
93
|
+
/** Inverts an 8-bit sRGB colour in OKLab space by flipping lightness `1 - L` and hue `(-a, -b)`. */
|
|
94
|
+
export declare function invertOklab8(r: number, g: number, b: number): [number, number, number];
|
|
95
|
+
/** Core (`0..1`) and soot-ring (`0..1`) weights for a heat value `h` in `0..1`. */
|
|
96
|
+
export declare function heatProfile(h: number): {
|
|
97
|
+
core: number;
|
|
98
|
+
ring: number;
|
|
99
|
+
};
|
|
100
|
+
export declare class AntimatterStrokeDriver {
|
|
101
|
+
readonly init: AntimatterStrokeInit;
|
|
102
|
+
dabCount: number;
|
|
103
|
+
bounds: RasterRect | null;
|
|
104
|
+
readonly blasts: AntimatterBlast[];
|
|
105
|
+
private readonly smoother;
|
|
106
|
+
private readonly copies;
|
|
107
|
+
private readonly states;
|
|
108
|
+
private readonly sampler;
|
|
109
|
+
private readonly sample;
|
|
110
|
+
private readonly effRgb;
|
|
111
|
+
private readonly heat;
|
|
112
|
+
private readonly heatCoords;
|
|
113
|
+
private tipBuf;
|
|
114
|
+
private lastRaw;
|
|
115
|
+
private lastFed;
|
|
116
|
+
private totalFuel;
|
|
117
|
+
private readonly reachedSkipped;
|
|
118
|
+
private readonly editedIds;
|
|
119
|
+
private readonly outputs;
|
|
120
|
+
constructor(init: AntimatterStrokeInit);
|
|
121
|
+
/** Pushes raw pen samples and returns the bounding rectangles of any blasts that fired. */
|
|
122
|
+
push(points: readonly PenPoint[]): RasterRect[];
|
|
123
|
+
/** Flushes the smoother tail and finishes the stroke. */
|
|
124
|
+
finish(): RasterRect[];
|
|
125
|
+
private processDabs;
|
|
126
|
+
/** Measures fuel (`0..1`) under `d` from the pre-stroke pixels of every visible layer. */
|
|
127
|
+
private measureFuel;
|
|
128
|
+
private fireBlast;
|
|
129
|
+
/** Writes one blast into `heatMap` (at `progress` 0..1) and returns the bounding rectangle including sparks. */
|
|
130
|
+
private writeBlastToHeat;
|
|
131
|
+
/** Recomposites all editable target layers from their pre-stroke tiles using the current committed `heat` and `blasts`. */
|
|
132
|
+
private recompositeAll;
|
|
133
|
+
/**
|
|
134
|
+
* Builds per-layer outputs for the given `heatMap` and blast progress function `progressOf(b)`.
|
|
135
|
+
* At `progressOf(b) === 1`, no flash or shock ring is drawn and sparks reach 100%, matching the
|
|
136
|
+
* committed pixels bit-for-bit.
|
|
137
|
+
*/
|
|
138
|
+
private buildOutputs;
|
|
139
|
+
/** Draws sparks and (when `progress < 1`) the view-only flash and expanding shock ring on the active layer. */
|
|
140
|
+
private drawActiveExtras;
|
|
141
|
+
/**
|
|
142
|
+
* Renders the blast state at `now` (ms) for view-only blast animation.
|
|
143
|
+
* When `active` is `false` (all blasts have reached `progress === 1`), `outputs` match `layerOutputs()` bit-for-bit.
|
|
144
|
+
*/
|
|
145
|
+
renderAtTime(now: number): {
|
|
146
|
+
outputs: AntimatterLayerOutput[];
|
|
147
|
+
active: boolean;
|
|
148
|
+
};
|
|
149
|
+
hasBlasts(): boolean;
|
|
150
|
+
/** Rebases blast birth times so the earliest blast starts at `now` ms. */
|
|
151
|
+
rebaseTime(now: number): void;
|
|
152
|
+
layerOutputs(): AntimatterLayerOutput[];
|
|
153
|
+
stats(): AntimatterStats;
|
|
154
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antimatter paint (`engine: 'antimatter'`, `marks.kind: 'antimatter'`): animated blasts that
|
|
3
|
+
* detonate where the brush touches paint across any visible layer, inverting colours in the core,
|
|
4
|
+
* removing alpha, burning a soot ring around the crater, denting thick relief, clearing core light,
|
|
5
|
+
* and throwing white-hot ballistic sparks on the active layer.
|
|
6
|
+
*/
|
|
7
|
+
import { type PaintGradientSource } from '../paint/gradient-paint.js';
|
|
8
|
+
import { TiledSurface, type RasterRect } from '../raster/surface.js';
|
|
9
|
+
import type { PaintBrush } from './brushes.js';
|
|
10
|
+
import { type EffectPaintPixels } from './effect-paint.js';
|
|
11
|
+
import { type PenPoint, type StrokeCopy } from './engine.js';
|
|
12
|
+
import { DEFAULT_ANTIMATTER, INVERT_MODES, normalizeAntimatter, type AntimatterSettings, type InvertMode } from './mark-settings.js';
|
|
13
|
+
import type { ThickChannels } from './thick.js';
|
|
14
|
+
export { DEFAULT_ANTIMATTER, INVERT_MODES, normalizeAntimatter, type AntimatterSettings, type InvertMode };
|
|
15
|
+
/** One detonation along an antimatter stroke. */
|
|
16
|
+
export interface AntimatterBlast {
|
|
17
|
+
index: number;
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
/** Blast radius in document pixels. */
|
|
21
|
+
radius: number;
|
|
22
|
+
/** Tip diameter at the dab that fired this blast. */
|
|
23
|
+
tipSize: number;
|
|
24
|
+
/** Tip opacity at the dab that fired this blast (`0..1`). */
|
|
25
|
+
tipOpacity: number;
|
|
26
|
+
/** Fuel (`0..1`) that triggered this blast. */
|
|
27
|
+
fuel: number;
|
|
28
|
+
/** Copy-specific seed for noise and sparks. */
|
|
29
|
+
seed: number;
|
|
30
|
+
/** Spark target colour (0..255 RGB). */
|
|
31
|
+
color: [number, number, number];
|
|
32
|
+
/** Light intensity (`0..1`) sparks write to `doc.light` on the active layer. */
|
|
33
|
+
lightAmount: number;
|
|
34
|
+
/** Number of sparks spawned by this blast. */
|
|
35
|
+
sparkCount: number;
|
|
36
|
+
/** Birth timestamp in ms (from `PenPoint.t` or the host clock). */
|
|
37
|
+
t: number;
|
|
38
|
+
}
|
|
39
|
+
/** Summary returned on `PaintStrokeResult.antimatter`. */
|
|
40
|
+
export interface AntimatterStats {
|
|
41
|
+
blasts: number;
|
|
42
|
+
sparks: number;
|
|
43
|
+
fuel: number;
|
|
44
|
+
layers: string[];
|
|
45
|
+
skippedLayers: string[];
|
|
46
|
+
}
|
|
47
|
+
/** One visible layer that supplies fuel to the antimatter stroke (and is edited if `editable`). */
|
|
48
|
+
export interface AntimatterTarget {
|
|
49
|
+
id: string;
|
|
50
|
+
/** True for unlocked pixel layers (not stroke, sticker or effect layers). */
|
|
51
|
+
editable: boolean;
|
|
52
|
+
lockTransparency: boolean;
|
|
53
|
+
opacity: number;
|
|
54
|
+
offset: {
|
|
55
|
+
x: number;
|
|
56
|
+
y: number;
|
|
57
|
+
};
|
|
58
|
+
/** Pre-stroke pixel surface (read-only fuel & recomposite source). */
|
|
59
|
+
base: TiledSurface;
|
|
60
|
+
/** Pre-stroke light channel (`doc.light[id]`), if any. */
|
|
61
|
+
baseLight?: TiledSurface | null;
|
|
62
|
+
/** Pre-stroke thick-paint channels (`doc.thick[id]`), if any. */
|
|
63
|
+
baseThick?: ThickChannels | null;
|
|
64
|
+
}
|
|
65
|
+
/** Per-layer output surfaces produced by `AntimatterStrokeDriver`. */
|
|
66
|
+
export interface AntimatterLayerOutput {
|
|
67
|
+
id: string;
|
|
68
|
+
surface: TiledSurface;
|
|
69
|
+
light: TiledSurface | null;
|
|
70
|
+
thick: ThickChannels | null;
|
|
71
|
+
changed: boolean;
|
|
72
|
+
}
|
|
73
|
+
export interface AntimatterStrokeInit {
|
|
74
|
+
activeLayerId: string;
|
|
75
|
+
targets: readonly AntimatterTarget[];
|
|
76
|
+
brush: PaintBrush;
|
|
77
|
+
/** Paint colour 0..255 RGBA. */
|
|
78
|
+
color: readonly [number, number, number, number];
|
|
79
|
+
seed: number;
|
|
80
|
+
copies: readonly StrokeCopy[];
|
|
81
|
+
selection?: {
|
|
82
|
+
width: number;
|
|
83
|
+
height: number;
|
|
84
|
+
data: ArrayLike<number>;
|
|
85
|
+
} | null;
|
|
86
|
+
paint?: PaintGradientSource | null;
|
|
87
|
+
effect?: EffectPaintPixels | null;
|
|
88
|
+
/** Current clock in ms for stamping blast birth times during live strokes. */
|
|
89
|
+
now?: () => number;
|
|
90
|
+
}
|
|
91
|
+
/** Smooth 2D value noise in `0..1` using only `Math.floor` and `hash2` (identical across TS and Swift). */
|
|
92
|
+
export declare function blastNoise2D(ux: number, uy: number, salt: number): number;
|
|
93
|
+
/** Inverts an 8-bit sRGB colour in OKLab space by flipping lightness `1 - L` and hue `(-a, -b)`. */
|
|
94
|
+
export declare function invertOklab8(r: number, g: number, b: number): [number, number, number];
|
|
95
|
+
/** Core (`0..1`) and soot-ring (`0..1`) weights for a heat value `h` in `0..1`. */
|
|
96
|
+
export declare function heatProfile(h: number): {
|
|
97
|
+
core: number;
|
|
98
|
+
ring: number;
|
|
99
|
+
};
|
|
100
|
+
export declare class AntimatterStrokeDriver {
|
|
101
|
+
readonly init: AntimatterStrokeInit;
|
|
102
|
+
dabCount: number;
|
|
103
|
+
bounds: RasterRect | null;
|
|
104
|
+
readonly blasts: AntimatterBlast[];
|
|
105
|
+
private readonly smoother;
|
|
106
|
+
private readonly copies;
|
|
107
|
+
private readonly states;
|
|
108
|
+
private readonly sampler;
|
|
109
|
+
private readonly sample;
|
|
110
|
+
private readonly effRgb;
|
|
111
|
+
private readonly heat;
|
|
112
|
+
private readonly heatCoords;
|
|
113
|
+
private tipBuf;
|
|
114
|
+
private lastRaw;
|
|
115
|
+
private lastFed;
|
|
116
|
+
private totalFuel;
|
|
117
|
+
private readonly reachedSkipped;
|
|
118
|
+
private readonly editedIds;
|
|
119
|
+
private readonly outputs;
|
|
120
|
+
constructor(init: AntimatterStrokeInit);
|
|
121
|
+
/** Pushes raw pen samples and returns the bounding rectangles of any blasts that fired. */
|
|
122
|
+
push(points: readonly PenPoint[]): RasterRect[];
|
|
123
|
+
/** Flushes the smoother tail and finishes the stroke. */
|
|
124
|
+
finish(): RasterRect[];
|
|
125
|
+
private processDabs;
|
|
126
|
+
/** Measures fuel (`0..1`) under `d` from the pre-stroke pixels of every visible layer. */
|
|
127
|
+
private measureFuel;
|
|
128
|
+
private fireBlast;
|
|
129
|
+
/** Writes one blast into `heatMap` (at `progress` 0..1) and returns the bounding rectangle including sparks. */
|
|
130
|
+
private writeBlastToHeat;
|
|
131
|
+
/** Recomposites all editable target layers from their pre-stroke tiles using the current committed `heat` and `blasts`. */
|
|
132
|
+
private recompositeAll;
|
|
133
|
+
/**
|
|
134
|
+
* Builds per-layer outputs for the given `heatMap` and blast progress function `progressOf(b)`.
|
|
135
|
+
* At `progressOf(b) === 1`, no flash or shock ring is drawn and sparks reach 100%, matching the
|
|
136
|
+
* committed pixels bit-for-bit.
|
|
137
|
+
*/
|
|
138
|
+
private buildOutputs;
|
|
139
|
+
/** Draws sparks and (when `progress < 1`) the view-only flash and expanding shock ring on the active layer. */
|
|
140
|
+
private drawActiveExtras;
|
|
141
|
+
/**
|
|
142
|
+
* Renders the blast state at `now` (ms) for view-only blast animation.
|
|
143
|
+
* When `active` is `false` (all blasts have reached `progress === 1`), `outputs` match `layerOutputs()` bit-for-bit.
|
|
144
|
+
*/
|
|
145
|
+
renderAtTime(now: number): {
|
|
146
|
+
outputs: AntimatterLayerOutput[];
|
|
147
|
+
active: boolean;
|
|
148
|
+
};
|
|
149
|
+
hasBlasts(): boolean;
|
|
150
|
+
/** Rebases blast birth times so the earliest blast starts at `now` ms. */
|
|
151
|
+
rebaseTime(now: number): void;
|
|
152
|
+
layerOutputs(): AntimatterLayerOutput[];
|
|
153
|
+
stats(): AntimatterStats;
|
|
154
|
+
}
|
|
@@ -47,6 +47,7 @@ export interface BrushEngineControls {
|
|
|
47
47
|
export declare const IRIDESCENCE_SLIDERS: readonly SliderControl[];
|
|
48
48
|
export declare const GHOST_SLIDERS: readonly SliderControl[];
|
|
49
49
|
export declare const MUTATION_SLIDERS: readonly SliderControl[];
|
|
50
|
+
export declare const ANTIMATTER_SLIDERS: readonly SliderControl[];
|
|
50
51
|
/**
|
|
51
52
|
* The controls the active brush's engine adds to the brush panel (`null` for the eraser):
|
|
52
53
|
* blender strength and blend distance; smudge strength and length; the Mixer Brush's pick-up,
|
|
@@ -47,6 +47,7 @@ export interface BrushEngineControls {
|
|
|
47
47
|
export declare const IRIDESCENCE_SLIDERS: readonly SliderControl[];
|
|
48
48
|
export declare const GHOST_SLIDERS: readonly SliderControl[];
|
|
49
49
|
export declare const MUTATION_SLIDERS: readonly SliderControl[];
|
|
50
|
+
export declare const ANTIMATTER_SLIDERS: readonly SliderControl[];
|
|
50
51
|
/**
|
|
51
52
|
* The controls the active brush's engine adds to the brush panel (`null` for the eraser):
|
|
52
53
|
* blender strength and blend distance; smudge strength and length; the Mixer Brush's pick-up,
|
|
@@ -9,14 +9,15 @@ import type { MixingModel } from '../paint/exchange.cjs';
|
|
|
9
9
|
import { type PaintGradientSource, type PaintSource } from '../paint/gradient-paint.cjs';
|
|
10
10
|
import { type MixerSettings } from '../paint/mixer.cjs';
|
|
11
11
|
import { DEFAULT_LIVE_PATTERNS, LIVE_PATTERN_KINDS, LIVE_PATTERN_PRESETS, normalizeLivePatterns, type LivePatternKind, type LivePatternsInput, type LivePatternsSettings } from '../paint/live-patterns.cjs';
|
|
12
|
-
import { type BristleSettings, type ParticleSettings, type StickerSettings } from './mark-settings.cjs';
|
|
13
|
-
export { DEFAULT_LIVE_PATTERNS, LIVE_PATTERN_KINDS, LIVE_PATTERN_PRESETS, normalizeLivePatterns, type LivePatternKind, type LivePatternsInput, type LivePatternsSettings };
|
|
12
|
+
import { DEFAULT_ANTIMATTER, INVERT_MODES, normalizeAntimatter, type AntimatterSettings, type BristleSettings, type InvertMode, type ParticleSettings, type StickerSettings } from './mark-settings.cjs';
|
|
13
|
+
export { DEFAULT_ANTIMATTER, DEFAULT_LIVE_PATTERNS, INVERT_MODES, LIVE_PATTERN_KINDS, LIVE_PATTERN_PRESETS, normalizeAntimatter, normalizeLivePatterns, type AntimatterSettings, type InvertMode, type LivePatternKind, type LivePatternsInput, type LivePatternsSettings, };
|
|
14
14
|
/**
|
|
15
15
|
* How a brush makes marks: `dab` (dabs into a stroke buffer, or dab by dab through the pick-up /
|
|
16
16
|
* mix exchange when its behaviour asks for it), `eraser` (removes alpha), `mixer` (the Mixer
|
|
17
|
-
* Brush), `blender` (mixes the colours under and near the tip)
|
|
17
|
+
* Brush), `blender` (mixes the colours under and near the tip), `smudge` (drags paint along), or
|
|
18
|
+
* `antimatter` (animated blasts that invert, scorch and destroy paint across every visible layer).
|
|
18
19
|
*/
|
|
19
|
-
export type PaintBrushEngine = 'dab' | 'eraser' | 'mixer' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker';
|
|
20
|
+
export type PaintBrushEngine = 'dab' | 'eraser' | 'mixer' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'antimatter';
|
|
20
21
|
export declare const PAINT_BRUSH_ENGINES: readonly PaintBrushEngine[];
|
|
21
22
|
export type PaintBrushCategory = 'pencil' | 'pastel' | 'charcoal' | 'airbrush' | 'marker' | 'ink' | 'paint' | 'eraser' | 'blender' | 'smudge' | 'mixer' | 'watercolor' | 'wet-tool' | 'oil' | 'impasto' | 'procedural' | 'bristle' | 'sticker' | 'light' | 'custom';
|
|
22
23
|
export declare const PAINT_BRUSH_CATEGORIES: readonly PaintBrushCategory[];
|
|
@@ -282,6 +283,8 @@ export interface PaintBrush {
|
|
|
282
283
|
bristle: BristleSettings;
|
|
283
284
|
/** Sticker engine only: the stamps and how they are sprayed. */
|
|
284
285
|
sticker: StickerSettings;
|
|
286
|
+
/** Antimatter engine only: blast size, spacing, threshold, inversion, scorch, annihilation, sparks, crater and duration. */
|
|
287
|
+
antimatter: AntimatterSettings;
|
|
285
288
|
/** Light paint: the light it lays with its colour (amount 0: none). */
|
|
286
289
|
light: LightSettings;
|
|
287
290
|
/** UV-fluorescent ink: glows under the virtual UV blacklight (amount 0: none). */
|
|
@@ -334,7 +337,7 @@ export interface SpraySettings {
|
|
|
334
337
|
size: number;
|
|
335
338
|
}
|
|
336
339
|
export declare const DEFAULT_SPRAY: Readonly<SpraySettings>;
|
|
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'>> & {
|
|
340
|
+
export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'antimatter' | 'paint' | 'light' | 'fluorescence' | 'thermochromic' | 'iridescence' | 'ghost' | 'mutation' | 'ferro' | 'spray' | 'tipGrain' | 'livePatterns'>> & {
|
|
338
341
|
spray?: Partial<SpraySettings> | null;
|
|
339
342
|
/** Tip grain (`null` removes it). */
|
|
340
343
|
tipGrain?: Partial<TipGrainSettings> | null;
|
|
@@ -363,6 +366,7 @@ export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mix
|
|
|
363
366
|
particle?: Partial<ParticleSettings>;
|
|
364
367
|
bristle?: Partial<BristleSettings>;
|
|
365
368
|
sticker?: Partial<StickerSettings>;
|
|
369
|
+
antimatter?: Partial<AntimatterSettings>;
|
|
366
370
|
};
|
|
367
371
|
/** Whether a brush can pick paint up from the canvas (the pick-up / mix ratios apply): dab, mixer and wet brushes. */
|
|
368
372
|
export declare function isWetCapable(brush: Pick<PaintBrush, 'engine'>): boolean;
|
|
@@ -9,14 +9,15 @@ import type { MixingModel } from '../paint/exchange.js';
|
|
|
9
9
|
import { type PaintGradientSource, type PaintSource } from '../paint/gradient-paint.js';
|
|
10
10
|
import { type MixerSettings } from '../paint/mixer.js';
|
|
11
11
|
import { DEFAULT_LIVE_PATTERNS, LIVE_PATTERN_KINDS, LIVE_PATTERN_PRESETS, normalizeLivePatterns, type LivePatternKind, type LivePatternsInput, type LivePatternsSettings } from '../paint/live-patterns.js';
|
|
12
|
-
import { type BristleSettings, type ParticleSettings, type StickerSettings } from './mark-settings.js';
|
|
13
|
-
export { DEFAULT_LIVE_PATTERNS, LIVE_PATTERN_KINDS, LIVE_PATTERN_PRESETS, normalizeLivePatterns, type LivePatternKind, type LivePatternsInput, type LivePatternsSettings };
|
|
12
|
+
import { DEFAULT_ANTIMATTER, INVERT_MODES, normalizeAntimatter, type AntimatterSettings, type BristleSettings, type InvertMode, type ParticleSettings, type StickerSettings } from './mark-settings.js';
|
|
13
|
+
export { DEFAULT_ANTIMATTER, DEFAULT_LIVE_PATTERNS, INVERT_MODES, LIVE_PATTERN_KINDS, LIVE_PATTERN_PRESETS, normalizeAntimatter, normalizeLivePatterns, type AntimatterSettings, type InvertMode, type LivePatternKind, type LivePatternsInput, type LivePatternsSettings, };
|
|
14
14
|
/**
|
|
15
15
|
* How a brush makes marks: `dab` (dabs into a stroke buffer, or dab by dab through the pick-up /
|
|
16
16
|
* mix exchange when its behaviour asks for it), `eraser` (removes alpha), `mixer` (the Mixer
|
|
17
|
-
* Brush), `blender` (mixes the colours under and near the tip)
|
|
17
|
+
* Brush), `blender` (mixes the colours under and near the tip), `smudge` (drags paint along), or
|
|
18
|
+
* `antimatter` (animated blasts that invert, scorch and destroy paint across every visible layer).
|
|
18
19
|
*/
|
|
19
|
-
export type PaintBrushEngine = 'dab' | 'eraser' | 'mixer' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker';
|
|
20
|
+
export type PaintBrushEngine = 'dab' | 'eraser' | 'mixer' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'antimatter';
|
|
20
21
|
export declare const PAINT_BRUSH_ENGINES: readonly PaintBrushEngine[];
|
|
21
22
|
export type PaintBrushCategory = 'pencil' | 'pastel' | 'charcoal' | 'airbrush' | 'marker' | 'ink' | 'paint' | 'eraser' | 'blender' | 'smudge' | 'mixer' | 'watercolor' | 'wet-tool' | 'oil' | 'impasto' | 'procedural' | 'bristle' | 'sticker' | 'light' | 'custom';
|
|
22
23
|
export declare const PAINT_BRUSH_CATEGORIES: readonly PaintBrushCategory[];
|
|
@@ -282,6 +283,8 @@ export interface PaintBrush {
|
|
|
282
283
|
bristle: BristleSettings;
|
|
283
284
|
/** Sticker engine only: the stamps and how they are sprayed. */
|
|
284
285
|
sticker: StickerSettings;
|
|
286
|
+
/** Antimatter engine only: blast size, spacing, threshold, inversion, scorch, annihilation, sparks, crater and duration. */
|
|
287
|
+
antimatter: AntimatterSettings;
|
|
285
288
|
/** Light paint: the light it lays with its colour (amount 0: none). */
|
|
286
289
|
light: LightSettings;
|
|
287
290
|
/** UV-fluorescent ink: glows under the virtual UV blacklight (amount 0: none). */
|
|
@@ -334,7 +337,7 @@ export interface SpraySettings {
|
|
|
334
337
|
size: number;
|
|
335
338
|
}
|
|
336
339
|
export declare const DEFAULT_SPRAY: Readonly<SpraySettings>;
|
|
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'>> & {
|
|
340
|
+
export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mixer' | 'behavior' | 'blender' | 'smudge' | 'wet' | 'impasto' | 'particle' | 'bristle' | 'sticker' | 'antimatter' | 'paint' | 'light' | 'fluorescence' | 'thermochromic' | 'iridescence' | 'ghost' | 'mutation' | 'ferro' | 'spray' | 'tipGrain' | 'livePatterns'>> & {
|
|
338
341
|
spray?: Partial<SpraySettings> | null;
|
|
339
342
|
/** Tip grain (`null` removes it). */
|
|
340
343
|
tipGrain?: Partial<TipGrainSettings> | null;
|
|
@@ -363,6 +366,7 @@ export type PaintBrushInput = Partial<Omit<PaintBrush, 'tip' | 'dynamics' | 'mix
|
|
|
363
366
|
particle?: Partial<ParticleSettings>;
|
|
364
367
|
bristle?: Partial<BristleSettings>;
|
|
365
368
|
sticker?: Partial<StickerSettings>;
|
|
369
|
+
antimatter?: Partial<AntimatterSettings>;
|
|
366
370
|
};
|
|
367
371
|
/** Whether a brush can pick paint up from the canvas (the pick-up / mix ratios apply): dab, mixer and wet brushes. */
|
|
368
372
|
export declare function isWetCapable(brush: Pick<PaintBrush, 'engine'>): boolean;
|
|
@@ -308,6 +308,8 @@ export interface PaintStrokeInit {
|
|
|
308
308
|
stencils?: boolean;
|
|
309
309
|
/** Mask with these stencils instead (replays pass the ones recorded with the stroke). */
|
|
310
310
|
maskStencils?: readonly Stencil[];
|
|
311
|
+
/** Antimatter strokes: the fuel layer ids (the visible pixel layers when painted). A replay reads fuel from exactly these and changes the editable ones, whatever is visible now. */
|
|
312
|
+
targets?: readonly string[];
|
|
311
313
|
}
|
|
312
314
|
export interface LayerUpdate {
|
|
313
315
|
name?: string;
|
|
@@ -511,6 +513,9 @@ export declare class PaintEditorController {
|
|
|
511
513
|
private cached;
|
|
512
514
|
private session;
|
|
513
515
|
private live;
|
|
516
|
+
private liveMulti;
|
|
517
|
+
private liveThickMulti;
|
|
518
|
+
private liveLightMulti;
|
|
514
519
|
private liveLayers;
|
|
515
520
|
private dirty;
|
|
516
521
|
private seedCounter;
|
|
@@ -528,6 +533,13 @@ export declare class PaintEditorController {
|
|
|
528
533
|
private liveEffectAt;
|
|
529
534
|
/** The view's stroke layers at `effectTime`, each with the document surface it was drawn from (stale once that changes). */
|
|
530
535
|
private animatedLayers;
|
|
536
|
+
/** Blast animation frames (view only), kept apart from live effect frames so neither replaces the other. */
|
|
537
|
+
private blastLayers;
|
|
538
|
+
/** Blast animation light / thick channels (`null` light: none at this frame). */
|
|
539
|
+
private animatedLight;
|
|
540
|
+
private animatedThick;
|
|
541
|
+
private activeBlastAnim;
|
|
542
|
+
private playingClock;
|
|
531
543
|
/** `renderAnimationFrame` / `withEffectTime`: layer surfaces at another time, for one render. */
|
|
532
544
|
private frameOverride;
|
|
533
545
|
/** The area each stroke painted (document pixels; `null`: nothing), learnt as it is painted or drawn, so a stroke layer edit redraws only where it changes (see `drawLiveStrokes`). */
|
|
@@ -1860,6 +1872,17 @@ export declare class PaintEditorController {
|
|
|
1860
1872
|
}): {
|
|
1861
1873
|
stop(): void;
|
|
1862
1874
|
};
|
|
1875
|
+
/**
|
|
1876
|
+
* The fuel layers of an antimatter stroke: every visible, non-temporary pixel layer (group
|
|
1877
|
+
* opacity multiplied in), or on a replay exactly the recorded `targetIds` whatever their
|
|
1878
|
+
* visibility now. The editable ones (not locked, stroke, sticker or effect layers) change.
|
|
1879
|
+
*/
|
|
1880
|
+
private antimatterTargetsOf;
|
|
1881
|
+
/** Applies every target layer's output from an antimatter stroke into a new document state. */
|
|
1882
|
+
private applyAntimatterOutputs;
|
|
1883
|
+
private startBlastAnimation;
|
|
1884
|
+
private stepBlastAnimation;
|
|
1885
|
+
private clearBlastAnimation;
|
|
1863
1886
|
/**
|
|
1864
1887
|
* Runs `fn` with the painting as it is `time` ms into its live effects (see `getAnimation`): for
|
|
1865
1888
|
* exports at a moment. Nothing in the document changes.
|
|
@@ -308,6 +308,8 @@ export interface PaintStrokeInit {
|
|
|
308
308
|
stencils?: boolean;
|
|
309
309
|
/** Mask with these stencils instead (replays pass the ones recorded with the stroke). */
|
|
310
310
|
maskStencils?: readonly Stencil[];
|
|
311
|
+
/** Antimatter strokes: the fuel layer ids (the visible pixel layers when painted). A replay reads fuel from exactly these and changes the editable ones, whatever is visible now. */
|
|
312
|
+
targets?: readonly string[];
|
|
311
313
|
}
|
|
312
314
|
export interface LayerUpdate {
|
|
313
315
|
name?: string;
|
|
@@ -511,6 +513,9 @@ export declare class PaintEditorController {
|
|
|
511
513
|
private cached;
|
|
512
514
|
private session;
|
|
513
515
|
private live;
|
|
516
|
+
private liveMulti;
|
|
517
|
+
private liveThickMulti;
|
|
518
|
+
private liveLightMulti;
|
|
514
519
|
private liveLayers;
|
|
515
520
|
private dirty;
|
|
516
521
|
private seedCounter;
|
|
@@ -528,6 +533,13 @@ export declare class PaintEditorController {
|
|
|
528
533
|
private liveEffectAt;
|
|
529
534
|
/** The view's stroke layers at `effectTime`, each with the document surface it was drawn from (stale once that changes). */
|
|
530
535
|
private animatedLayers;
|
|
536
|
+
/** Blast animation frames (view only), kept apart from live effect frames so neither replaces the other. */
|
|
537
|
+
private blastLayers;
|
|
538
|
+
/** Blast animation light / thick channels (`null` light: none at this frame). */
|
|
539
|
+
private animatedLight;
|
|
540
|
+
private animatedThick;
|
|
541
|
+
private activeBlastAnim;
|
|
542
|
+
private playingClock;
|
|
531
543
|
/** `renderAnimationFrame` / `withEffectTime`: layer surfaces at another time, for one render. */
|
|
532
544
|
private frameOverride;
|
|
533
545
|
/** The area each stroke painted (document pixels; `null`: nothing), learnt as it is painted or drawn, so a stroke layer edit redraws only where it changes (see `drawLiveStrokes`). */
|
|
@@ -1860,6 +1872,17 @@ export declare class PaintEditorController {
|
|
|
1860
1872
|
}): {
|
|
1861
1873
|
stop(): void;
|
|
1862
1874
|
};
|
|
1875
|
+
/**
|
|
1876
|
+
* The fuel layers of an antimatter stroke: every visible, non-temporary pixel layer (group
|
|
1877
|
+
* opacity multiplied in), or on a replay exactly the recorded `targetIds` whatever their
|
|
1878
|
+
* visibility now. The editable ones (not locked, stroke, sticker or effect layers) change.
|
|
1879
|
+
*/
|
|
1880
|
+
private antimatterTargetsOf;
|
|
1881
|
+
/** Applies every target layer's output from an antimatter stroke into a new document state. */
|
|
1882
|
+
private applyAntimatterOutputs;
|
|
1883
|
+
private startBlastAnimation;
|
|
1884
|
+
private stepBlastAnimation;
|
|
1885
|
+
private clearBlastAnimation;
|
|
1863
1886
|
/**
|
|
1864
1887
|
* Runs `fn` with the painting as it is `time` ms into its live effects (see `getAnimation`): for
|
|
1865
1888
|
* exports at a moment. Nothing in the document changes.
|