@pixerate/editor 0.248.0 → 0.249.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/README.md +1 -0
- package/dist/animation-editor/index.cjs +64 -61
- package/dist/animation-editor/index.js +8 -5
- package/dist/{brushstrokeRender-DTDPFBLC.cjs → brushstrokeRender-GCKK7V2I.cjs} +14 -11
- package/dist/{brushstrokeRender-QLCXROJK.js → brushstrokeRender-T3JZST44.js} +7 -4
- package/dist/canvas/index.cjs +8 -8
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-IBDU6EGZ.cjs → chunk-2SMMZDMG.cjs} +35 -35
- package/dist/{chunk-SC2RZ5EF.js → chunk-2VJAVXLI.js} +2 -2
- package/dist/{chunk-OLNIPTB3.cjs → chunk-2VX55NFM.cjs} +1 -320
- package/dist/chunk-3K6HWEXZ.cjs +92 -0
- package/dist/{chunk-UOOK7HTX.js → chunk-3PPJRMIG.js} +1 -1
- package/dist/chunk-4D6KP5BV.js +92 -0
- package/dist/chunk-5RH3VXAK.js +269 -0
- package/dist/{chunk-NZ3O3A5C.js → chunk-6BIDVPED.js} +1 -1
- package/dist/{chunk-2ONK3ERD.cjs → chunk-75K3W4D6.cjs} +20 -20
- package/dist/{chunk-7T7JWTVE.cjs → chunk-BOHDJJ2O.cjs} +8 -8
- package/dist/{chunk-2PBZBRP5.js → chunk-D5KGAO4Z.js} +10 -92
- package/dist/{chunk-5GLYUSNT.js → chunk-DOIU7VJG.js} +1 -1
- package/dist/{chunk-HB4ICNNA.cjs → chunk-DPYAO5U6.cjs} +42 -42
- package/dist/chunk-EJLRBS5Q.js +301 -0
- package/dist/{chunk-6G6ZDDDB.cjs → chunk-H4AOUUBE.cjs} +301 -149
- package/dist/{chunk-PQ3H2AAN.cjs → chunk-I7NJPHWV.cjs} +122 -204
- package/dist/{chunk-L6REDLNB.cjs → chunk-IOFVM3L3.cjs} +7 -7
- package/dist/{chunk-42TWUPNJ.js → chunk-IRSTHLQQ.js} +1 -320
- package/dist/{chunk-VNBUDVD4.js → chunk-J7T5QZ45.js} +226 -74
- package/dist/{chunk-VMROIWLL.cjs → chunk-KBYB7OWB.cjs} +3 -3
- package/dist/{chunk-TPWB4Y6L.cjs → chunk-KYX7NZ5V.cjs} +1 -1
- package/dist/chunk-LJRCU3BJ.cjs +301 -0
- package/dist/{chunk-WVS5KQDH.cjs → chunk-LP2MCSBE.cjs} +246 -244
- package/dist/{chunk-XNRBMYNB.js → chunk-O75V4ZS3.js} +1 -1
- package/dist/chunk-OTTT5N3K.js +322 -0
- package/dist/{chunk-Q2HA52V4.js → chunk-PZP2SZIZ.js} +2 -2
- package/dist/{chunk-ZFSLEOSQ.js → chunk-UBRJOIR5.js} +11 -9
- package/dist/chunk-W5M3J7PV.cjs +322 -0
- package/dist/{chunk-4P6H35HU.js → chunk-WA44NKPF.js} +2 -2
- package/dist/{chunk-XWTRATIM.cjs → chunk-WLJZZHUZ.cjs} +23 -23
- package/dist/{chunk-P3NIPIKS.js → chunk-WQCNC4DK.js} +1 -1
- package/dist/chunk-ZEYMKDYS.cjs +269 -0
- package/dist/image-editor/index.cjs +1055 -1050
- package/dist/image-editor/index.js +28 -23
- package/dist/paint/index.cjs +8 -5
- package/dist/paint/index.js +13 -10
- package/dist/paint-editor/controller.d.cts +37 -1
- package/dist/paint-editor/controller.d.ts +37 -1
- package/dist/paint-editor/index.cjs +745 -602
- package/dist/paint-editor/index.d.cts +3 -0
- package/dist/paint-editor/index.d.ts +3 -0
- package/dist/paint-editor/index.js +184 -41
- package/dist/paint-editor/sticker-art.d.cts +55 -0
- package/dist/paint-editor/sticker-art.d.ts +55 -0
- package/dist/paint-editor/stickers.d.cts +30 -17
- package/dist/paint-editor/stickers.d.ts +30 -17
- package/dist/paint-editor/stroke.d.cts +4 -0
- package/dist/paint-editor/stroke.d.ts +4 -0
- package/dist/paint-editor/ui.d.cts +10 -2
- package/dist/paint-editor/ui.d.ts +10 -2
- package/dist/raster/index.cjs +6 -4
- package/dist/raster/index.js +12 -10
- package/dist/stickers/browser.d.cts +48 -0
- package/dist/stickers/browser.d.ts +48 -0
- package/dist/stickers/combine.d.cts +10 -0
- package/dist/stickers/combine.d.ts +10 -0
- package/dist/stickers/conformance.d.cts +18 -0
- package/dist/stickers/conformance.d.ts +18 -0
- package/dist/stickers/editor.d.cts +14 -0
- package/dist/stickers/editor.d.ts +14 -0
- package/dist/stickers/errors.d.cts +6 -0
- package/dist/stickers/errors.d.ts +6 -0
- package/dist/stickers/fake.d.cts +16 -0
- package/dist/stickers/fake.d.ts +16 -0
- package/dist/stickers/helpers.d.cts +51 -0
- package/dist/stickers/helpers.d.ts +51 -0
- package/dist/stickers/index.cjs +331 -0
- package/dist/stickers/index.d.cts +16 -0
- package/dist/stickers/index.d.ts +16 -0
- package/dist/stickers/index.js +331 -0
- package/dist/stickers/stamps.d.cts +13 -0
- package/dist/stickers/stamps.d.ts +13 -0
- package/dist/stickers/tools.d.cts +25 -0
- package/dist/stickers/tools.d.ts +25 -0
- package/dist/stickers/types.d.cts +123 -0
- package/dist/stickers/types.d.ts +123 -0
- package/dist/vector/index.cjs +978 -975
- package/dist/vector/index.js +9 -6
- package/package.json +11 -1
- package/skills/README.md +1 -0
- package/skills/pixerate-paint-editor/SKILL.md +8 -5
- package/skills/pixerate-stickers/SKILL.md +45 -0
|
@@ -51,3 +51,6 @@ export type { WetBackendInfo } from '../paint/wet/world.cjs';
|
|
|
51
51
|
export * from '../paint/gradient-paint.cjs';
|
|
52
52
|
export * from './playback.cjs';
|
|
53
53
|
export * from './editorDocument.cjs';
|
|
54
|
+
export { StickerBrowser, type StickerBrowserItem, type StickerBrowserState } from '../stickers/browser.cjs';
|
|
55
|
+
export type { StickerProvider, StickerRef, StickerSummary } from '../stickers/types.cjs';
|
|
56
|
+
export * from './sticker-art.cjs';
|
|
@@ -51,3 +51,6 @@ export type { WetBackendInfo } from '../paint/wet/world.js';
|
|
|
51
51
|
export * from '../paint/gradient-paint.js';
|
|
52
52
|
export * from './playback.js';
|
|
53
53
|
export * from './editorDocument.js';
|
|
54
|
+
export { StickerBrowser, type StickerBrowserItem, type StickerBrowserState } from '../stickers/browser.js';
|
|
55
|
+
export type { StickerProvider, StickerRef, StickerSummary } from '../stickers/types.js';
|
|
56
|
+
export * from './sticker-art.js';
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StickerBrowser,
|
|
3
|
+
editorStickers
|
|
4
|
+
} from "../chunk-EJLRBS5Q.js";
|
|
1
5
|
import {
|
|
2
6
|
toVideoFfmpeg
|
|
3
7
|
} from "../chunk-L3JFOTBQ.js";
|
|
@@ -8,7 +12,7 @@ import {
|
|
|
8
12
|
resolveExternalAssets,
|
|
9
13
|
serializeLayers,
|
|
10
14
|
serializeLayersExternal
|
|
11
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-UBRJOIR5.js";
|
|
12
16
|
import "../chunk-3CI7FRMK.js";
|
|
13
17
|
import "../chunk-ZNA3IQZF.js";
|
|
14
18
|
import {
|
|
@@ -26,7 +30,7 @@ import {
|
|
|
26
30
|
mergeLayerEffect,
|
|
27
31
|
newEffectId,
|
|
28
32
|
validateLayerEffects
|
|
29
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-3PPJRMIG.js";
|
|
30
34
|
import "../chunk-OHKOFKBY.js";
|
|
31
35
|
import "../chunk-ZIF4UJJ6.js";
|
|
32
36
|
import {
|
|
@@ -53,7 +57,7 @@ import {
|
|
|
53
57
|
pigmentOf,
|
|
54
58
|
pointerPressure,
|
|
55
59
|
wetSupport
|
|
56
|
-
} from "../chunk-
|
|
60
|
+
} from "../chunk-WQCNC4DK.js";
|
|
57
61
|
import "../chunk-HVQVHUTV.js";
|
|
58
62
|
import {
|
|
59
63
|
writeZip
|
|
@@ -64,7 +68,7 @@ import {
|
|
|
64
68
|
realPresenceClock,
|
|
65
69
|
tweenPresenceCursor
|
|
66
70
|
} from "../chunk-IVSWRVB4.js";
|
|
67
|
-
import "../chunk-
|
|
71
|
+
import "../chunk-PZP2SZIZ.js";
|
|
68
72
|
import {
|
|
69
73
|
BRUSH_ID,
|
|
70
74
|
BRUSH_ROTATIONS,
|
|
@@ -89,6 +93,7 @@ import {
|
|
|
89
93
|
IDENTITY_COPY,
|
|
90
94
|
IMPASTO_TOOLS,
|
|
91
95
|
MAX_DOT_TEXTURES,
|
|
96
|
+
MAX_STICKER_STAMPS,
|
|
92
97
|
MULTI_COLOR_MODES,
|
|
93
98
|
PAINT_BRUSH_CATEGORIES,
|
|
94
99
|
PAINT_BRUSH_ENGINES,
|
|
@@ -100,7 +105,8 @@ import {
|
|
|
100
105
|
PenDabWalker,
|
|
101
106
|
PenSmoother,
|
|
102
107
|
RIBBON_PAIRS,
|
|
103
|
-
|
|
108
|
+
STICKER_ART_SIZE,
|
|
109
|
+
StickerArtCache,
|
|
104
110
|
StickerSpray,
|
|
105
111
|
WET_MEDIA,
|
|
106
112
|
WET_TOOLS,
|
|
@@ -108,6 +114,7 @@ import {
|
|
|
108
114
|
brushTakesPaint,
|
|
109
115
|
brushToJSON,
|
|
110
116
|
clonePaper,
|
|
117
|
+
defaultStickerRasterizer,
|
|
111
118
|
drawSticker,
|
|
112
119
|
effectDabField,
|
|
113
120
|
effectPaintKey,
|
|
@@ -138,16 +145,25 @@ import {
|
|
|
138
145
|
readPaintEffectPaint,
|
|
139
146
|
renderPaper,
|
|
140
147
|
renderStickers,
|
|
148
|
+
sampleArt,
|
|
141
149
|
sampleEffectAt,
|
|
142
150
|
sampleEffectField,
|
|
143
|
-
stampCoverage,
|
|
144
151
|
stickerAt,
|
|
145
152
|
stickerRect,
|
|
153
|
+
stickerStamp,
|
|
146
154
|
stickerSurface,
|
|
147
155
|
tiltToOrientation,
|
|
148
156
|
toStrokePoint,
|
|
149
157
|
usesPaintExchange
|
|
150
|
-
} from "../chunk-
|
|
158
|
+
} from "../chunk-J7T5QZ45.js";
|
|
159
|
+
import {
|
|
160
|
+
STAMP_KINDS,
|
|
161
|
+
StickersSlot,
|
|
162
|
+
createStickerTools,
|
|
163
|
+
editorStampOf,
|
|
164
|
+
normalizeStickerRef,
|
|
165
|
+
stampCoverage
|
|
166
|
+
} from "../chunk-5RH3VXAK.js";
|
|
151
167
|
import "../chunk-M6DNZNVY.js";
|
|
152
168
|
import "../chunk-WEIK3UYB.js";
|
|
153
169
|
import "../chunk-PWBZH3FK.js";
|
|
@@ -188,7 +204,6 @@ import {
|
|
|
188
204
|
PaperGrain,
|
|
189
205
|
SmudgeTip,
|
|
190
206
|
TileMedium,
|
|
191
|
-
TileableNoise,
|
|
192
207
|
addPaintGradientStop,
|
|
193
208
|
applyStrokeToTile,
|
|
194
209
|
blenderDab,
|
|
@@ -198,46 +213,51 @@ import {
|
|
|
198
213
|
exchangeRates,
|
|
199
214
|
grainCatch,
|
|
200
215
|
grainHeights,
|
|
201
|
-
hash2,
|
|
202
216
|
hexToPaintRgb,
|
|
203
217
|
isGradientPaint,
|
|
204
218
|
loadMixer,
|
|
205
|
-
mix32,
|
|
206
219
|
mixerRates,
|
|
207
220
|
normalizeHexColor,
|
|
208
221
|
paintGradientMappingFor,
|
|
209
222
|
paintSourceColor,
|
|
210
223
|
paintSourceCss,
|
|
211
224
|
parsePaintSource,
|
|
212
|
-
rand01,
|
|
213
|
-
randSigned,
|
|
214
225
|
rasterizeDab,
|
|
215
226
|
readPaintSource,
|
|
216
227
|
removePaintGradientStop,
|
|
217
228
|
resolvePaintGradient,
|
|
218
229
|
reversePaintGradient,
|
|
219
230
|
scalePaintGradient,
|
|
220
|
-
seedFromString,
|
|
221
231
|
solidPaint,
|
|
222
232
|
updatePaintGradientStop
|
|
223
|
-
} from "../chunk-
|
|
233
|
+
} from "../chunk-D5KGAO4Z.js";
|
|
234
|
+
import {
|
|
235
|
+
TileableNoise,
|
|
236
|
+
hash2,
|
|
237
|
+
mix32,
|
|
238
|
+
rand01,
|
|
239
|
+
randSigned,
|
|
240
|
+
seedFromString
|
|
241
|
+
} from "../chunk-4D6KP5BV.js";
|
|
224
242
|
import "../chunk-ODBT55Q7.js";
|
|
225
243
|
import {
|
|
226
244
|
BLEND_MODES,
|
|
227
245
|
PAINTERLY_BLEND_MODES,
|
|
246
|
+
isBlendMode,
|
|
247
|
+
isPainterlyBlendMode,
|
|
248
|
+
mixPigment8,
|
|
249
|
+
mixPigments,
|
|
250
|
+
standardBlendMode
|
|
251
|
+
} from "../chunk-IRSTHLQQ.js";
|
|
252
|
+
import {
|
|
228
253
|
base64ToBytes,
|
|
229
254
|
bytesToBase64,
|
|
230
255
|
decodePng,
|
|
231
256
|
encodePng,
|
|
232
|
-
isBlendMode,
|
|
233
|
-
isPainterlyBlendMode,
|
|
234
257
|
isPng,
|
|
235
|
-
mixPigment8,
|
|
236
|
-
mixPigments,
|
|
237
258
|
parseDataUrl,
|
|
238
|
-
pngDataUrl
|
|
239
|
-
|
|
240
|
-
} from "../chunk-42TWUPNJ.js";
|
|
259
|
+
pngDataUrl
|
|
260
|
+
} from "../chunk-OTTT5N3K.js";
|
|
241
261
|
import {
|
|
242
262
|
TILE,
|
|
243
263
|
TiledSurface,
|
|
@@ -1305,7 +1325,7 @@ var PaintStrokeSession = class _PaintStrokeSession {
|
|
|
1305
1325
|
};
|
|
1306
1326
|
if (this.wetDriver) {
|
|
1307
1327
|
} else if (init.sticker) {
|
|
1308
|
-
this.stickerSpray = new StickerSpray({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: init.paint ?? null, effect });
|
|
1328
|
+
this.stickerSpray = new StickerSpray({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: init.paint ?? null, effect, art: init.sticker.art });
|
|
1309
1329
|
} else if (init.thick) {
|
|
1310
1330
|
const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
|
|
1311
1331
|
this.thickDriver = new ThickStrokeDriver({ brush, target: this.tileTarget(), channels: init.thick.channels, color: rgb(init.color), load: init.mixerLoad, seed: init.seed, copies: this.copies, paint: init.paint ?? null, effect });
|
|
@@ -1515,6 +1535,7 @@ var PaintStrokeSession = class _PaintStrokeSession {
|
|
|
1515
1535
|
const surface = changed ? new TiledSurface(ch, tiles, this.base.defaultValue) : null;
|
|
1516
1536
|
const dabs = this.dry ? this.dry.dabCount : this.thickDriver ? this.thickDriver.dabCount : this.stickerSpray ? this.stickerSpray.dabCount : this.wet.dabCount;
|
|
1517
1537
|
this.result = { layerId: this.layerId, bounds: changed ? this.bounds : null, dabs, strokeId: null };
|
|
1538
|
+
if (this.stickerSpray?.skipped.size) this.result.skippedStickers = [...this.stickerSpray.skipped];
|
|
1518
1539
|
const carried = this.wet?.load ?? this.thickDriver?.load;
|
|
1519
1540
|
if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : cleanMixer(carried);
|
|
1520
1541
|
this.host.commit(this, surface, false);
|
|
@@ -4161,10 +4182,16 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
4161
4182
|
wetOp = null;
|
|
4162
4183
|
/** The effects provider slot (see `setEffectsProvider`). */
|
|
4163
4184
|
effects = new EffectsSlot();
|
|
4185
|
+
/** The sticker library slot (see `setStickersProvider`). */
|
|
4186
|
+
stickers = new StickersSlot(editorStickers());
|
|
4187
|
+
stickerArt = new StickerArtCache();
|
|
4188
|
+
rasterizeSticker;
|
|
4164
4189
|
effectsRenderer = new PaintEffectsRenderer();
|
|
4165
4190
|
paperEffectNodeCache = null;
|
|
4166
4191
|
constructor(options = {}) {
|
|
4167
4192
|
this.historyLimit = Math.max(1, options.historyLimit ?? 200);
|
|
4193
|
+
this.rasterizeSticker = options.rasterizeSticker ?? defaultStickerRasterizer;
|
|
4194
|
+
if (options.stickers) this.stickers.set(options.stickers);
|
|
4168
4195
|
this.doc = createPaintDocument({ width: options.width, height: options.height, dpi: options.dpi, paper: this.resolvePaper(options.paper) });
|
|
4169
4196
|
this.userBrushes = (options.brushes ?? []).map((b) => normalizePaintBrush({ ...b, builtin: false }));
|
|
4170
4197
|
const start = this.findBrush(options.brushId ?? DEFAULT_BRUSH_ID) ?? this.findBrush(DEFAULT_BRUSH_ID);
|
|
@@ -5323,6 +5350,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
5323
5350
|
else delete next.builtin;
|
|
5324
5351
|
this.brush = next;
|
|
5325
5352
|
this.emit([]);
|
|
5353
|
+
if (next.engine === "sticker" && next.sticker.stamps.some((r) => !editorStampOf(r))) void this.prepareStickers(next.sticker.stamps).catch(() => this.emit([]));
|
|
5326
5354
|
return this.brush;
|
|
5327
5355
|
}
|
|
5328
5356
|
/** Saves the active brush (or `brush`) into the user library under `id` / `name`. */
|
|
@@ -5648,7 +5676,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
5648
5676
|
thick: brush.engine === "impasto" ? { channels: doc.thick?.[layer.id] ?? emptyThickChannels() } : void 0,
|
|
5649
5677
|
// Light paint: a twin of the stroke paints the light channel (laying, dimming, moving light).
|
|
5650
5678
|
light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || doc.light?.[layer.id]) ? { surface: doc.light?.[layer.id] ?? emptyLight() } : null,
|
|
5651
|
-
sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc) } : void 0,
|
|
5679
|
+
sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc), art: this.stickerArt.get } : void 0,
|
|
5652
5680
|
paint: effect ? null : this.strokeGradient(init, brush, color),
|
|
5653
5681
|
effect
|
|
5654
5682
|
});
|
|
@@ -6445,9 +6473,19 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6445
6473
|
const stickers = {};
|
|
6446
6474
|
for (const [id, list] of Object.entries(ext.stickers)) {
|
|
6447
6475
|
if (!findLayer(state.layers, id) || !Array.isArray(list)) continue;
|
|
6448
|
-
const ok = list.
|
|
6476
|
+
const ok = list.flatMap((x) => {
|
|
6477
|
+
if (!x || typeof x.id !== "string" || !Number.isFinite(x.x) || !Number.isFinite(x.y) || !(x.size > 0)) return [];
|
|
6478
|
+
try {
|
|
6479
|
+
const ref2 = normalizeStickerRef(x.ref ?? x.stamp);
|
|
6480
|
+
const stamp = editorStampOf(ref2);
|
|
6481
|
+
const { stamp: _old, ...rest } = x;
|
|
6482
|
+
return [{ ...rest, ref: ref2, ...stamp ? { stamp } : {} }];
|
|
6483
|
+
} catch {
|
|
6484
|
+
return [];
|
|
6485
|
+
}
|
|
6486
|
+
});
|
|
6449
6487
|
if (ok.length !== list.length) problems.push(`Some stickers of layer "${id}" could not be read; they were dropped.`);
|
|
6450
|
-
stickers[id] = ok
|
|
6488
|
+
stickers[id] = ok;
|
|
6451
6489
|
}
|
|
6452
6490
|
if (Object.keys(stickers).length) state = { ...state, stickers };
|
|
6453
6491
|
}
|
|
@@ -6551,6 +6589,8 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6551
6589
|
delete this.extensions.paperEffect;
|
|
6552
6590
|
this.viewCompositor.clear();
|
|
6553
6591
|
this.emit();
|
|
6592
|
+
const refs = Object.values(this.doc.stickers ?? {}).flatMap((list) => list.map((x) => x.ref));
|
|
6593
|
+
if (refs.some((r) => !editorStampOf(r))) void this.prepareStickers(refs).catch(() => this.emit([]));
|
|
6554
6594
|
return loaded.problems;
|
|
6555
6595
|
}
|
|
6556
6596
|
/** Opens a saved document (clears the history). Returns what could not be read. */
|
|
@@ -6878,6 +6918,56 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6878
6918
|
if (!stickers) throw new PaintEditorError(`Layer "${l.name}" has no stickers; spray some with a sticker brush (list_brushes category sticker).`);
|
|
6879
6919
|
return { layer: l, stickers };
|
|
6880
6920
|
}
|
|
6921
|
+
// --- The sticker library ---------------------------------------------------------
|
|
6922
|
+
/** The sticker library: the editor's own stamps unless a host set its own. */
|
|
6923
|
+
get stickersProvider() {
|
|
6924
|
+
return this.stickers.provider;
|
|
6925
|
+
}
|
|
6926
|
+
/**
|
|
6927
|
+
* Sets the sticker library (`null` goes back to the editor's own stamps, `editorStickers()`);
|
|
6928
|
+
* to offer both, pass `combineStickerProviders([editorStickers(), yours])`. Loaded art is
|
|
6929
|
+
* forgotten. Not an edit: no undo step.
|
|
6930
|
+
*/
|
|
6931
|
+
setStickersProvider(provider) {
|
|
6932
|
+
if ((provider ?? this.stickers.fallback) === this.stickers.provider) return;
|
|
6933
|
+
this.stickers.set(provider);
|
|
6934
|
+
this.stickerArt.clear();
|
|
6935
|
+
this.emit([]);
|
|
6936
|
+
}
|
|
6937
|
+
/**
|
|
6938
|
+
* Loads the art of `refs` (provider stickers; editor stamps need none) so sprays and placements
|
|
6939
|
+
* can draw them. Rejects with a `PaintEditorError` naming an unknown ref and the closest known
|
|
6940
|
+
* ones, or a sticker whose art failed. Emits when art arrives, so views redraw.
|
|
6941
|
+
*/
|
|
6942
|
+
async prepareStickers(refs) {
|
|
6943
|
+
const list = [...new Set(refs.map((r) => this.readStickerRef(r)))].filter((r) => !editorStampOf(r));
|
|
6944
|
+
try {
|
|
6945
|
+
await Promise.all(list.map((r) => this.stickerArt.ensure(this.stickers.provider, r, this.rasterizeSticker)));
|
|
6946
|
+
} catch (e) {
|
|
6947
|
+
throw new PaintEditorError(e instanceof Error ? e.message : String(e));
|
|
6948
|
+
} finally {
|
|
6949
|
+
if (list.length) this.emit([]);
|
|
6950
|
+
}
|
|
6951
|
+
}
|
|
6952
|
+
/** Whether a sticker's art is ready to draw: `ready` (always for editor stamps), `loading`, `failed` (with why) or `none`. */
|
|
6953
|
+
stickerArtStatus(ref2) {
|
|
6954
|
+
return this.stickerArt.status(this.readStickerRef(ref2));
|
|
6955
|
+
}
|
|
6956
|
+
readStickerRef(ref2) {
|
|
6957
|
+
try {
|
|
6958
|
+
return normalizeStickerRef(ref2);
|
|
6959
|
+
} catch (e) {
|
|
6960
|
+
throw new PaintEditorError(e.message);
|
|
6961
|
+
}
|
|
6962
|
+
}
|
|
6963
|
+
/** Refuses to redraw stickers whose art has not loaded (they would vanish), naming them and what to call. */
|
|
6964
|
+
requireStickerArt(stickers) {
|
|
6965
|
+
const missing = [...new Set(stickers.filter((s) => !stickerStamp(s) && !this.stickerArt.get(s.ref)).map((s) => s.ref))];
|
|
6966
|
+
if (missing.length) {
|
|
6967
|
+
for (const r of missing) void this.stickerArt.ensure(this.stickers.provider, r, this.rasterizeSticker).then(() => this.emit([]), () => this.emit([]));
|
|
6968
|
+
throw new PaintEditorError(`The art for ${missing.map((r) => `"${r}"`).join(", ")} has not loaded yet; it is loading now (prepareStickers), so try again when it has.`);
|
|
6969
|
+
}
|
|
6970
|
+
}
|
|
6881
6971
|
/** A layer's stickers, bottom first. */
|
|
6882
6972
|
listStickers(layerId) {
|
|
6883
6973
|
const id = layerId ?? this.doc.activeLayerId;
|
|
@@ -6891,6 +6981,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6891
6981
|
*/
|
|
6892
6982
|
commitStickers(label, layer, stickers, dirty) {
|
|
6893
6983
|
if (isLayerLocked(layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it first.`);
|
|
6984
|
+
this.requireStickerArt(stickers);
|
|
6894
6985
|
const before = this.previewBase() ?? this.doc;
|
|
6895
6986
|
this.stickerPreview = null;
|
|
6896
6987
|
const surface = this.redrawStickers(layer, stickers, dirty);
|
|
@@ -6899,7 +6990,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6899
6990
|
}
|
|
6900
6991
|
redrawStickers(layer, stickers, dirty) {
|
|
6901
6992
|
const partial = dirty && !layer.offset.x && !layer.offset.y;
|
|
6902
|
-
return partial ? stickerSurface(stickers, layer.surface, dirty) : stickerSurface(stickers);
|
|
6993
|
+
return partial ? stickerSurface(stickers, layer.surface, dirty, this.stickerArt.get) : stickerSurface(stickers, void 0, void 0, this.stickerArt.get);
|
|
6903
6994
|
}
|
|
6904
6995
|
/** The document from before the sticker preview on screen, or `null` when none is (anything else changed the document since). */
|
|
6905
6996
|
previewBase() {
|
|
@@ -6918,7 +7009,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6918
7009
|
const id = layerId ?? this.doc.activeLayerId;
|
|
6919
7010
|
if (!id) return null;
|
|
6920
7011
|
this.requireLayer(id);
|
|
6921
|
-
const hit = stickerAt(this.doc.stickers?.[id] ?? [], x, y);
|
|
7012
|
+
const hit = stickerAt(this.doc.stickers?.[id] ?? [], x, y, this.stickerArt.get);
|
|
6922
7013
|
return hit ? { ...hit } : null;
|
|
6923
7014
|
}
|
|
6924
7015
|
/** Picks a sticker for the panel and canvas (`null` for none). Editor state, not an undo step. */
|
|
@@ -6972,7 +7063,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6972
7063
|
*/
|
|
6973
7064
|
addStickers(layerId, input) {
|
|
6974
7065
|
const layer = this.wetLayer(layerId, "add stickers to");
|
|
6975
|
-
if (!input.length) throw new PaintEditorError("Pass at least one sticker (
|
|
7066
|
+
if (!input.length) throw new PaintEditorError("Pass at least one sticker (ref, x, y).");
|
|
6976
7067
|
if (input.length > MAX_ADD_STICKERS) throw new PaintEditorError(`At most ${MAX_ADD_STICKERS} stickers per call; split them over several calls.`);
|
|
6977
7068
|
const existing = this.doc.stickers?.[layer.id];
|
|
6978
7069
|
if (!existing?.length) {
|
|
@@ -6980,7 +7071,8 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6980
7071
|
}
|
|
6981
7072
|
let n = this.nextStickerNumber();
|
|
6982
7073
|
const added = input.map((raw, i) => {
|
|
6983
|
-
|
|
7074
|
+
if (raw.ref === void 0 && raw.stamp === void 0) throw new PaintEditorError(`Sticker ${i} needs ref (a sticker ref from find_stickers, e.g. "editor:star").`);
|
|
7075
|
+
for (const k of ["x", "y"]) if (raw[k] === void 0) throw new PaintEditorError(`Sticker ${i} needs ${k}.`);
|
|
6984
7076
|
let u;
|
|
6985
7077
|
try {
|
|
6986
7078
|
u = this.readStickerUpdate(raw);
|
|
@@ -8045,7 +8137,7 @@ function createPaintStickerTools(c) {
|
|
|
8045
8137
|
{
|
|
8046
8138
|
name: "list_stickers",
|
|
8047
8139
|
title: "List stickers",
|
|
8048
|
-
description: "Lists a layer\u2019s stickers bottom first: id, stamp, x, y (centre, document pixels), size (diameter px), rotation (degrees clockwise), color, opacity. Empty for a layer without stickers. Changes nothing.",
|
|
8140
|
+
description: "Lists a layer\u2019s stickers bottom first: id, ref (provider:id; stamp too for the editor\u2019s own), x, y (centre, document pixels), size (diameter px), rotation (degrees clockwise), color, opacity. Empty for a layer without stickers. Changes nothing.",
|
|
8049
8141
|
inputSchema: { type: "object", properties: { layerId: LAYER_ID }, additionalProperties: false },
|
|
8050
8142
|
annotations: { title: "List stickers", ...READ },
|
|
8051
8143
|
coordinates: { out: ["stickers[]"] },
|
|
@@ -8072,7 +8164,7 @@ function createPaintStickerTools(c) {
|
|
|
8072
8164
|
{
|
|
8073
8165
|
name: "add_stickers",
|
|
8074
8166
|
title: "Place stickers",
|
|
8075
|
-
description: "Places stickers exactly where you say, on top of a sticker layer or onto an empty layer (which becomes a sticker layer). Use it for deliberate placement; spray with paint_stroke and a sticker brush for a random scatter. One undo step. Returns the new stickers with their ids, for update_sticker, arrange_stickers and remove_stickers.",
|
|
8167
|
+
description: "Places stickers exactly where you say, on top of a sticker layer or onto an empty layer (which becomes a sticker layer): any sticker from the sticker library by ref (find_stickers), its art loaded first; tintable ones take color. Use it for deliberate placement; spray with paint_stroke and a sticker brush for a random scatter. An unknown ref is refused with the closest ones. One undo step. Returns the new stickers with their ids, for update_sticker, arrange_stickers and remove_stickers.",
|
|
8076
8168
|
inputSchema: {
|
|
8077
8169
|
type: "object",
|
|
8078
8170
|
properties: {
|
|
@@ -8085,7 +8177,8 @@ function createPaintStickerTools(c) {
|
|
|
8085
8177
|
items: {
|
|
8086
8178
|
type: "object",
|
|
8087
8179
|
properties: {
|
|
8088
|
-
|
|
8180
|
+
ref: { type: "string", minLength: 1, description: "The sticker: a ref provider:id from find_stickers (e.g. editor:star). Give ref or stamp." },
|
|
8181
|
+
stamp: { type: "string", enum: [...STAMP_KINDS], description: "Older form: an editor stamp (same as ref editor:<stamp>)." },
|
|
8089
8182
|
x: { type: "number", description: "Centre x in document pixels." },
|
|
8090
8183
|
y: { type: "number", description: "Centre y in document pixels." },
|
|
8091
8184
|
size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels (default 48)." },
|
|
@@ -8094,7 +8187,7 @@ function createPaintStickerTools(c) {
|
|
|
8094
8187
|
opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0..1 (default 1)." },
|
|
8095
8188
|
seed: { type: "integer", minimum: 0, description: "Texture seed (default from the new id); splat and confetti shapes vary with it." }
|
|
8096
8189
|
},
|
|
8097
|
-
required: ["
|
|
8190
|
+
required: ["x", "y"],
|
|
8098
8191
|
additionalProperties: false
|
|
8099
8192
|
}
|
|
8100
8193
|
}
|
|
@@ -8104,7 +8197,14 @@ function createPaintStickerTools(c) {
|
|
|
8104
8197
|
},
|
|
8105
8198
|
annotations: { title: "Place stickers", ...WRITE },
|
|
8106
8199
|
coordinates: { in: ["stickers[]"], out: ["stickers[]"] },
|
|
8107
|
-
handler: ({ layerId, stickers }) =>
|
|
8200
|
+
handler: async ({ layerId, stickers }) => {
|
|
8201
|
+
const list = stickers;
|
|
8202
|
+
list.forEach((x, i) => {
|
|
8203
|
+
if (x.ref === void 0 && x.stamp === void 0) throw new Error(`Sticker ${i} needs ref (a sticker ref from find_stickers, e.g. "editor:star").`);
|
|
8204
|
+
});
|
|
8205
|
+
await c.prepareStickers(list.map((x) => x.ref ?? `editor:${x.stamp}`));
|
|
8206
|
+
return { layerId: layerId ?? c.document.activeLayerId, stickers: c.addStickers(layerId, list) };
|
|
8207
|
+
}
|
|
8108
8208
|
},
|
|
8109
8209
|
{
|
|
8110
8210
|
name: "update_sticker",
|
|
@@ -8115,7 +8215,8 @@ function createPaintStickerTools(c) {
|
|
|
8115
8215
|
properties: {
|
|
8116
8216
|
layerId: LAYER_ID,
|
|
8117
8217
|
id: { type: "string", description: "Sticker id from list_stickers." },
|
|
8118
|
-
|
|
8218
|
+
ref: { type: "string", minLength: 1, description: "Another sticker: a ref provider:id from find_stickers." },
|
|
8219
|
+
stamp: { type: "string", enum: [...STAMP_KINDS], description: "Older form: another editor stamp (same as ref editor:<stamp>)." },
|
|
8119
8220
|
x: { type: "number", description: "Centre x in document pixels." },
|
|
8120
8221
|
y: { type: "number", description: "Centre y in document pixels." },
|
|
8121
8222
|
size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels." },
|
|
@@ -8128,7 +8229,11 @@ function createPaintStickerTools(c) {
|
|
|
8128
8229
|
},
|
|
8129
8230
|
annotations: { title: "Change a sticker", ...WRITE },
|
|
8130
8231
|
coordinates: { in: [""], out: [""] },
|
|
8131
|
-
handler: ({ layerId, id, ...update }) =>
|
|
8232
|
+
handler: async ({ layerId, id, ...update }) => {
|
|
8233
|
+
const refs = c.listStickers(layerId).map((s) => s.ref);
|
|
8234
|
+
await c.prepareStickers(update.ref ? [...refs, update.ref] : refs);
|
|
8235
|
+
return c.updateSticker(layerId, id, update);
|
|
8236
|
+
}
|
|
8132
8237
|
},
|
|
8133
8238
|
{
|
|
8134
8239
|
name: "arrange_stickers",
|
|
@@ -8145,7 +8250,10 @@ function createPaintStickerTools(c) {
|
|
|
8145
8250
|
additionalProperties: false
|
|
8146
8251
|
},
|
|
8147
8252
|
annotations: { title: "Bring stickers forward or back", ...WRITE },
|
|
8148
|
-
handler: ({ layerId, ids, to }) =>
|
|
8253
|
+
handler: async ({ layerId, ids, to }) => {
|
|
8254
|
+
await c.prepareStickers(c.listStickers(layerId).map((s) => s.ref));
|
|
8255
|
+
return { order: c.arrangeStickers(layerId, ids, to) };
|
|
8256
|
+
}
|
|
8149
8257
|
},
|
|
8150
8258
|
{
|
|
8151
8259
|
name: "remove_stickers",
|
|
@@ -8153,7 +8261,10 @@ function createPaintStickerTools(c) {
|
|
|
8153
8261
|
description: "Deletes stickers by id, or every sticker on the layer when ids is missing. One undo step. Returns the ids removed.",
|
|
8154
8262
|
inputSchema: { type: "object", properties: { layerId: LAYER_ID, ids: { type: "array", items: { type: "string", description: "Sticker id." }, description: "Sticker ids (default all)." } }, additionalProperties: false },
|
|
8155
8263
|
annotations: { title: "Delete stickers", ...DESTRUCTIVE },
|
|
8156
|
-
handler: ({ layerId, ids }) =>
|
|
8264
|
+
handler: async ({ layerId, ids }) => {
|
|
8265
|
+
await c.prepareStickers(c.listStickers(layerId).map((s) => s.ref));
|
|
8266
|
+
return { removed: c.removeStickers(layerId, ids) };
|
|
8267
|
+
}
|
|
8157
8268
|
}
|
|
8158
8269
|
];
|
|
8159
8270
|
}
|
|
@@ -9167,7 +9278,13 @@ var STICKER_BRUSH = {
|
|
|
9167
9278
|
type: "object",
|
|
9168
9279
|
description: "Sticker engine settings: stamps sprayed along the stroke as editable stickers. Missing fields keep their current values.",
|
|
9169
9280
|
properties: {
|
|
9170
|
-
stamps: {
|
|
9281
|
+
stamps: {
|
|
9282
|
+
type: "array",
|
|
9283
|
+
minItems: 1,
|
|
9284
|
+
maxItems: MAX_STICKER_STAMPS,
|
|
9285
|
+
items: { type: "string", minLength: 1, description: "A sticker ref provider:id from find_stickers (e.g. editor:star); a bare editor stamp (star) means editor:star." },
|
|
9286
|
+
description: `The stickers to spray, one picked at random per sticker: refs from find_stickers (the editor's own: ${STAMP_KINDS.map((k) => `editor:${k}`).join(", ")}). Each is checked against the sticker library and an unknown ref is refused with the closest ones. A provider's sticker is drawn from its art (tinted to the paint colour when tintable), loaded before the stroke.`
|
|
9287
|
+
},
|
|
9171
9288
|
density: { type: "number", minimum: 0, maximum: 1, description: "How closely stickers follow each other: about density \xD7 4 stickers per tip diameter of travel (0.25 \u2248 one per diameter, 1 \u2248 four). Default 0.4." },
|
|
9172
9289
|
sizeJitter: { type: "number", minimum: 0, maximum: 1, description: "Random size change." },
|
|
9173
9290
|
rotationJitter: { type: "number", minimum: 0, maximum: 1, description: "Random turn as a fraction of \xB1180\xB0." },
|
|
@@ -9594,7 +9711,11 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
9594
9711
|
description: "Chooses the active brush (id) and / or changes its settings; strokes without a brush use it. Editor state, not an undo step. Changes stay on the active brush until save_brush stores them. Returns the active brush.",
|
|
9595
9712
|
inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brushes to start from." }, ...BRUSH_FIELDS }, additionalProperties: false },
|
|
9596
9713
|
annotations: { title: "Set the brush", ...SET4 },
|
|
9597
|
-
handler: (a) =>
|
|
9714
|
+
handler: async (a) => {
|
|
9715
|
+
const stamps = a.sticker?.stamps;
|
|
9716
|
+
if (stamps) await c.prepareStickers(stamps);
|
|
9717
|
+
return brushToJSON(c.setBrush(a));
|
|
9718
|
+
}
|
|
9598
9719
|
});
|
|
9599
9720
|
add({
|
|
9600
9721
|
name: "save_brush",
|
|
@@ -9770,6 +9891,9 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
9770
9891
|
coordinates: { in: ["points[]"], out: ["bounds"] },
|
|
9771
9892
|
handler: async (a) => {
|
|
9772
9893
|
await c.wetIdle();
|
|
9894
|
+
const base = a.brushId ? c.getBrush(a.brushId) : c.getState().brush;
|
|
9895
|
+
const over = a.brush;
|
|
9896
|
+
if ((over?.engine ?? base?.engine) === "sticker") await c.prepareStickers(over?.sticker?.stamps ?? base?.sticker.stamps ?? []);
|
|
9773
9897
|
const stroke = { points: a.points, layerId: a.layerId, brushId: a.brushId, brush: a.brush, color: a.color, paint: a.paint, seed: a.seed, snapToPerspective: a.snapToPerspective };
|
|
9774
9898
|
const r = await act({ kind: "stroke", stroke }, () => c.paintStroke(stroke));
|
|
9775
9899
|
return r.mixerLoad ? { ...r, mixerLoad: loadResult(r.mixerLoad) } : r;
|
|
@@ -10078,6 +10202,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
10078
10202
|
tools.push(...createPaintReplayTools(c));
|
|
10079
10203
|
tools.push(...createPaintStickerTools(c));
|
|
10080
10204
|
tools.push(...createPigmentTools());
|
|
10205
|
+
tools.push(...createStickerTools({ provider: () => c.stickersProvider }));
|
|
10081
10206
|
tools.push(
|
|
10082
10207
|
...createLayerEffectTools(
|
|
10083
10208
|
{
|
|
@@ -10251,7 +10376,7 @@ var PaintGesture = class {
|
|
|
10251
10376
|
}
|
|
10252
10377
|
const brush = this.controller.getState().brush;
|
|
10253
10378
|
const size = Math.min(2048, Math.max(2, Math.round(brush.tip.size)));
|
|
10254
|
-
const [added] = this.controller.addStickers(void 0, [{
|
|
10379
|
+
const [added] = this.controller.addStickers(void 0, [{ ref: brush.sticker.stamps[0] ?? "editor:star", x: round2(p.x), y: round2(p.y), size }]);
|
|
10255
10380
|
this.controller.selectSticker(added.id);
|
|
10256
10381
|
} catch (err) {
|
|
10257
10382
|
this.error = err instanceof Error ? err.message : String(err);
|
|
@@ -10787,6 +10912,15 @@ var RIBBON_PAIR_LABELS = { adjacent: "Neighbours", "first-last": "Outermost" };
|
|
|
10787
10912
|
var DOT_TEXTURE_ORDER_LABELS = { sequence: "In turn", random: "Random" };
|
|
10788
10913
|
var DOT_ROTATION_LABELS = { follow: "Follow motion", random: "Random", fixed: "Tip angle" };
|
|
10789
10914
|
var STAMP_LABELS = { dot: "Dot", star: "Star", heart: "Heart", leaf: "Leaf", flower: "Flower", confetti: "Confetti", splat: "Splat", sparkle: "Sparkle", ring: "Ring" };
|
|
10915
|
+
function toggleStickerRef(refs, ref2) {
|
|
10916
|
+
if (refs.includes(ref2)) return refs.length > 1 ? refs.filter((r) => r !== ref2) : [...refs];
|
|
10917
|
+
return refs.length < MAX_STICKER_STAMPS ? [...refs, ref2] : [...refs];
|
|
10918
|
+
}
|
|
10919
|
+
function stickerRefLabel(ref2) {
|
|
10920
|
+
const stamp = ref2.startsWith("editor:") ? ref2.slice(7) : null;
|
|
10921
|
+
if (stamp && STAMP_LABELS[stamp]) return STAMP_LABELS[stamp];
|
|
10922
|
+
return ref2.slice(ref2.indexOf(":") + 1);
|
|
10923
|
+
}
|
|
10790
10924
|
function toggleStamp(stamps, stamp) {
|
|
10791
10925
|
const next = stamps.includes(stamp) ? stamps.filter((s) => s !== stamp) : [...stamps, stamp];
|
|
10792
10926
|
return next.length ? next : [stamp];
|
|
@@ -11141,6 +11275,7 @@ export {
|
|
|
11141
11275
|
MAX_DOT_TEXTURES,
|
|
11142
11276
|
MAX_IMAGE_SIDE,
|
|
11143
11277
|
MAX_LIVE_EFFECT_SOURCES,
|
|
11278
|
+
MAX_STICKER_STAMPS,
|
|
11144
11279
|
MAX_ZOOM,
|
|
11145
11280
|
MIN_CANVAS_SIDE,
|
|
11146
11281
|
MIN_ZOOM,
|
|
@@ -11205,10 +11340,13 @@ export {
|
|
|
11205
11340
|
STAMP_LABELS,
|
|
11206
11341
|
STENCIL_KINDS,
|
|
11207
11342
|
STENCIL_SHAPES,
|
|
11343
|
+
STICKER_ART_SIZE,
|
|
11208
11344
|
STICKER_SLIDERS,
|
|
11209
11345
|
STROKE_SLIDERS,
|
|
11210
11346
|
SYMMETRY_MODES,
|
|
11211
11347
|
StencilSnapper,
|
|
11348
|
+
StickerArtCache,
|
|
11349
|
+
StickerBrowser,
|
|
11212
11350
|
StickerSpray,
|
|
11213
11351
|
TRACING_NODE_ID,
|
|
11214
11352
|
ThickStrokeDriver,
|
|
@@ -11256,6 +11394,7 @@ export {
|
|
|
11256
11394
|
decodeImageBlob,
|
|
11257
11395
|
defaultGuides,
|
|
11258
11396
|
defaultImageEncoder,
|
|
11397
|
+
defaultStickerRasterizer,
|
|
11259
11398
|
deserializePaintDocument,
|
|
11260
11399
|
deserializePaintDocumentAsync,
|
|
11261
11400
|
documentExtensions,
|
|
@@ -11374,6 +11513,7 @@ export {
|
|
|
11374
11513
|
rgbToHexColor,
|
|
11375
11514
|
rgbToHsl,
|
|
11376
11515
|
rgbToHsv,
|
|
11516
|
+
sampleArt,
|
|
11377
11517
|
sampleEffectAt,
|
|
11378
11518
|
sampleEffectField,
|
|
11379
11519
|
samplePressure,
|
|
@@ -11391,6 +11531,8 @@ export {
|
|
|
11391
11531
|
stencilOutline,
|
|
11392
11532
|
stickerAt,
|
|
11393
11533
|
stickerRect,
|
|
11534
|
+
stickerRefLabel,
|
|
11535
|
+
stickerStamp,
|
|
11394
11536
|
stickerSurface,
|
|
11395
11537
|
strokeBounds,
|
|
11396
11538
|
strokeDuration,
|
|
@@ -11408,6 +11550,7 @@ export {
|
|
|
11408
11550
|
toStrokePoint,
|
|
11409
11551
|
toggleDotTexture,
|
|
11410
11552
|
toggleStamp,
|
|
11553
|
+
toggleStickerRef,
|
|
11411
11554
|
translateStencil,
|
|
11412
11555
|
updatePaintGradientStop,
|
|
11413
11556
|
usesPaintExchange,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Art for stickers from a sticker provider (anything but the editor's own procedural stamps): the
|
|
3
|
+
* spray brush draws while a stroke is in progress, so it can't wait for a provider. Each sticker
|
|
4
|
+
* is loaded once, rasterised to RGBA and kept here; drawing reads it synchronously.
|
|
5
|
+
*
|
|
6
|
+
* PNG art (`data:` URLs) is decoded here, in any environment. SVG and `https:` images need a
|
|
7
|
+
* rasteriser: the browser's (`createImageBitmap` and `OffscreenCanvas`) by default, or the
|
|
8
|
+
* host's (`PaintEditorOptions.rasterizeSticker`).
|
|
9
|
+
*/
|
|
10
|
+
import type { StickerAsset, StickerProvider, StickerRef } from '../stickers/types.cjs';
|
|
11
|
+
/** Rasterised sticker art (straight RGBA) and whether to recolour it. */
|
|
12
|
+
export interface StickerArt {
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
data: Uint8ClampedArray;
|
|
16
|
+
/** Flat art: drawn in the sticker's colour, keeping its alpha. */
|
|
17
|
+
tintable: boolean;
|
|
18
|
+
}
|
|
19
|
+
/** The art for a ref, when it has loaded. */
|
|
20
|
+
export type StickerArtLookup = (ref: StickerRef) => StickerArt | undefined;
|
|
21
|
+
/** Turns a sticker asset into RGBA at about `size` px on its longest side. */
|
|
22
|
+
export type StickerRasterizer = (asset: StickerAsset, size: number) => Promise<{
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
data: Uint8ClampedArray;
|
|
26
|
+
}>;
|
|
27
|
+
/** Longest side sticker art is kept at (px); larger stickers are drawn from it, smoothly scaled. */
|
|
28
|
+
export declare const STICKER_ART_SIZE = 256;
|
|
29
|
+
/**
|
|
30
|
+
* Decodes PNG data URLs anywhere; draws SVG and other images with the browser's
|
|
31
|
+
* `createImageBitmap` and `OffscreenCanvas` when present, and otherwise refuses, naming the option
|
|
32
|
+
* that adds a rasteriser.
|
|
33
|
+
*/
|
|
34
|
+
export declare const defaultStickerRasterizer: StickerRasterizer;
|
|
35
|
+
/** Loaded sticker art by ref, with the state of each load. */
|
|
36
|
+
export declare class StickerArtCache {
|
|
37
|
+
private readonly entries;
|
|
38
|
+
/** The art for `ref` when it has loaded (editor stamps never need any). */
|
|
39
|
+
get: StickerArtLookup;
|
|
40
|
+
/** `ready`, `loading`, `failed` (with the reason) or `none` (never asked for). Editor stamps are always `ready`. */
|
|
41
|
+
status(ref: StickerRef): {
|
|
42
|
+
status: 'ready' | 'loading' | 'failed' | 'none';
|
|
43
|
+
error?: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Loads and rasterises `ref` from `provider` once (later calls share the load). Unknown refs
|
|
47
|
+
* reject with the closest known ones; failures are kept so they are reported, and retried on
|
|
48
|
+
* the next call.
|
|
49
|
+
*/
|
|
50
|
+
ensure(provider: StickerProvider, ref: StickerRef, rasterize: StickerRasterizer): Promise<StickerArt | null>;
|
|
51
|
+
/** Forgets every load (a new provider). */
|
|
52
|
+
clear(): void;
|
|
53
|
+
}
|
|
54
|
+
/** Bilinear RGBA sample of `art` at (x, y) in its pixels (straight alpha, colour weighted by alpha). */
|
|
55
|
+
export declare function sampleArt(art: StickerArt, x: number, y: number, out: number[]): number[];
|