@pixerate/editor 0.248.0 → 0.250.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 +118 -114
- package/dist/animation-editor/index.js +11 -7
- package/dist/{brushstrokeRender-QLCXROJK.js → brushstrokeRender-2FHFLSEG.js} +8 -4
- package/dist/{brushstrokeRender-DTDPFBLC.cjs → brushstrokeRender-QGRXOKDA.cjs} +15 -11
- package/dist/canvas/index.cjs +71 -15
- package/dist/canvas/index.d.cts +1 -0
- package/dist/canvas/index.d.ts +1 -0
- package/dist/canvas/index.js +58 -2
- package/dist/canvas/stickers.d.cts +35 -0
- package/dist/canvas/stickers.d.ts +35 -0
- package/dist/{chunk-RXZL4NG5.js → chunk-226QDRO3.js} +1 -1
- 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-ZFSLEOSQ.js → chunk-3TWOCSCY.js} +11 -9
- package/dist/chunk-4D6KP5BV.js +92 -0
- package/dist/chunk-4JNWA3VT.cjs +302 -0
- package/dist/{chunk-L3JFOTBQ.js → chunk-5E2Q7ZHI.js} +1 -1
- package/dist/{chunk-2ONK3ERD.cjs → chunk-75K3W4D6.cjs} +20 -20
- package/dist/{chunk-AU6MWQKZ.js → chunk-ABL7IWFZ.js} +1 -1
- package/dist/chunk-ATK6ABN3.cjs +303 -0
- package/dist/{chunk-7T7JWTVE.cjs → chunk-BOHDJJ2O.cjs} +8 -8
- package/dist/{chunk-2PBZBRP5.js → chunk-D5KGAO4Z.js} +10 -92
- package/dist/{chunk-HB4ICNNA.cjs → chunk-DPYAO5U6.cjs} +42 -42
- package/dist/{chunk-6G6ZDDDB.cjs → chunk-GT77U7QG.cjs} +303 -149
- package/dist/{chunk-PQ3H2AAN.cjs → chunk-I7NJPHWV.cjs} +122 -204
- package/dist/{chunk-42TWUPNJ.js → chunk-IRSTHLQQ.js} +1 -320
- package/dist/{chunk-GHCSC2WP.cjs → chunk-ISIO63Q5.cjs} +21 -15
- package/dist/{chunk-OFH6Q67U.js → chunk-JA57JIT5.js} +9 -3
- package/dist/{chunk-VMROIWLL.cjs → chunk-KBYB7OWB.cjs} +3 -3
- package/dist/{chunk-Q2HA52V4.js → chunk-KDLBJ6QR.js} +2 -2
- package/dist/{chunk-WVS5KQDH.cjs → chunk-M2VKFE5L.cjs} +246 -244
- package/dist/{chunk-5GLYUSNT.js → chunk-NOHJP5TK.js} +1 -1
- package/dist/{chunk-XNRBMYNB.js → chunk-NTRAVM2I.js} +1 -1
- package/dist/{chunk-VNBUDVD4.js → chunk-OTEPAQJX.js} +228 -74
- package/dist/chunk-OTTT5N3K.js +322 -0
- package/dist/{chunk-QOBCBGGI.cjs → chunk-QKXO6JPP.cjs} +14 -14
- package/dist/{chunk-NZ3O3A5C.js → chunk-SMSGP2HQ.js} +1 -1
- package/dist/chunk-SZTI6EER.js +13 -0
- package/dist/chunk-U4NUOKBT.js +303 -0
- package/dist/chunk-U67EN7GG.cjs +13 -0
- package/dist/chunk-W5M3J7PV.cjs +322 -0
- package/dist/{chunk-4P6H35HU.js → chunk-WA44NKPF.js} +2 -2
- package/dist/chunk-WKH5ZAUA.js +302 -0
- package/dist/{chunk-L6REDLNB.cjs → chunk-WPUXGDH4.cjs} +7 -7
- package/dist/{chunk-P3NIPIKS.js → chunk-WQCNC4DK.js} +1 -1
- package/dist/{chunk-IBDU6EGZ.cjs → chunk-X7WRL5ZZ.cjs} +35 -35
- package/dist/{chunk-XWTRATIM.cjs → chunk-YM6ZBTXG.cjs} +23 -23
- package/dist/{chunk-TPWB4Y6L.cjs → chunk-YW43M56C.cjs} +1 -1
- package/dist/{chunk-K5DS2JTA.cjs → chunk-Z3BRH4JK.cjs} +6 -6
- package/dist/{chunk-XNZFVYC2.cjs → chunk-ZBCT5MEA.cjs} +7 -7
- package/dist/effects/helpers.d.cts +6 -0
- package/dist/effects/helpers.d.ts +6 -0
- package/dist/effects/index.cjs +62 -60
- package/dist/effects/index.js +5 -3
- package/dist/effects/tools.d.cts +6 -0
- package/dist/effects/tools.d.ts +6 -0
- package/dist/image-editor/effects.d.cts +1 -1
- package/dist/image-editor/effects.d.ts +1 -1
- package/dist/image-editor/index.cjs +1097 -1069
- package/dist/image-editor/index.d.cts +1 -0
- package/dist/image-editor/index.d.ts +1 -0
- package/dist/image-editor/index.js +58 -30
- package/dist/image-editor/stickers.d.cts +9 -0
- package/dist/image-editor/stickers.d.ts +9 -0
- 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 +753 -609
- package/dist/paint-editor/index.d.cts +3 -0
- package/dist/paint-editor/index.d.ts +3 -0
- package/dist/paint-editor/index.js +187 -43
- 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 +337 -0
- package/dist/stickers/index.d.cts +16 -0
- package/dist/stickers/index.d.ts +16 -0
- package/dist/stickers/index.js +337 -0
- package/dist/stickers/stamps.d.cts +13 -0
- package/dist/stickers/stamps.d.ts +13 -0
- package/dist/stickers/tools.d.cts +81 -0
- package/dist/stickers/tools.d.ts +81 -0
- package/dist/stickers/types.d.cts +123 -0
- package/dist/stickers/types.d.ts +123 -0
- package/dist/vector/index.cjs +1018 -981
- package/dist/vector/index.d.cts +1 -0
- package/dist/vector/index.d.ts +1 -0
- package/dist/vector/index.js +44 -7
- package/dist/vector/stickers.d.cts +11 -0
- package/dist/vector/stickers.d.ts +11 -0
- package/dist/video-editor/index.cjs +344 -344
- package/dist/video-editor/index.js +4 -4
- package/package.json +11 -1
- package/skills/README.md +1 -0
- package/skills/pixerate-image-editor/SKILL.md +1 -1
- package/skills/pixerate-paint-editor/SKILL.md +8 -5
- package/skills/pixerate-stickers/SKILL.md +57 -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,6 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StickerBrowser,
|
|
3
|
+
editorStickers
|
|
4
|
+
} from "../chunk-U4NUOKBT.js";
|
|
1
5
|
import {
|
|
2
6
|
toVideoFfmpeg
|
|
3
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-5E2Q7ZHI.js";
|
|
4
8
|
import {
|
|
5
9
|
createLayerEffectTools,
|
|
6
10
|
deserializeLayers,
|
|
@@ -8,7 +12,7 @@ import {
|
|
|
8
12
|
resolveExternalAssets,
|
|
9
13
|
serializeLayers,
|
|
10
14
|
serializeLayersExternal
|
|
11
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-3TWOCSCY.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-KDLBJ6QR.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,19 +145,29 @@ 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-OTEPAQJX.js";
|
|
159
|
+
import {
|
|
160
|
+
STAMP_KINDS,
|
|
161
|
+
StickersSlot,
|
|
162
|
+
createStickerTools,
|
|
163
|
+
editorStampOf,
|
|
164
|
+
normalizeStickerRef,
|
|
165
|
+
stampCoverage
|
|
166
|
+
} from "../chunk-WKH5ZAUA.js";
|
|
151
167
|
import "../chunk-M6DNZNVY.js";
|
|
152
168
|
import "../chunk-WEIK3UYB.js";
|
|
153
169
|
import "../chunk-PWBZH3FK.js";
|
|
170
|
+
import "../chunk-SZTI6EER.js";
|
|
154
171
|
import {
|
|
155
172
|
EffectRendererPool
|
|
156
173
|
} from "../chunk-EHLOCVWB.js";
|
|
@@ -159,7 +176,7 @@ import {
|
|
|
159
176
|
EffectsSlot,
|
|
160
177
|
createEffectToolProvider,
|
|
161
178
|
resolveEffectValues
|
|
162
|
-
} from "../chunk-
|
|
179
|
+
} from "../chunk-JA57JIT5.js";
|
|
163
180
|
import "../chunk-V2ZCJRDM.js";
|
|
164
181
|
import {
|
|
165
182
|
CoverageMap,
|
|
@@ -188,7 +205,6 @@ import {
|
|
|
188
205
|
PaperGrain,
|
|
189
206
|
SmudgeTip,
|
|
190
207
|
TileMedium,
|
|
191
|
-
TileableNoise,
|
|
192
208
|
addPaintGradientStop,
|
|
193
209
|
applyStrokeToTile,
|
|
194
210
|
blenderDab,
|
|
@@ -198,46 +214,51 @@ import {
|
|
|
198
214
|
exchangeRates,
|
|
199
215
|
grainCatch,
|
|
200
216
|
grainHeights,
|
|
201
|
-
hash2,
|
|
202
217
|
hexToPaintRgb,
|
|
203
218
|
isGradientPaint,
|
|
204
219
|
loadMixer,
|
|
205
|
-
mix32,
|
|
206
220
|
mixerRates,
|
|
207
221
|
normalizeHexColor,
|
|
208
222
|
paintGradientMappingFor,
|
|
209
223
|
paintSourceColor,
|
|
210
224
|
paintSourceCss,
|
|
211
225
|
parsePaintSource,
|
|
212
|
-
rand01,
|
|
213
|
-
randSigned,
|
|
214
226
|
rasterizeDab,
|
|
215
227
|
readPaintSource,
|
|
216
228
|
removePaintGradientStop,
|
|
217
229
|
resolvePaintGradient,
|
|
218
230
|
reversePaintGradient,
|
|
219
231
|
scalePaintGradient,
|
|
220
|
-
seedFromString,
|
|
221
232
|
solidPaint,
|
|
222
233
|
updatePaintGradientStop
|
|
223
|
-
} from "../chunk-
|
|
234
|
+
} from "../chunk-D5KGAO4Z.js";
|
|
235
|
+
import {
|
|
236
|
+
TileableNoise,
|
|
237
|
+
hash2,
|
|
238
|
+
mix32,
|
|
239
|
+
rand01,
|
|
240
|
+
randSigned,
|
|
241
|
+
seedFromString
|
|
242
|
+
} from "../chunk-4D6KP5BV.js";
|
|
224
243
|
import "../chunk-ODBT55Q7.js";
|
|
225
244
|
import {
|
|
226
245
|
BLEND_MODES,
|
|
227
246
|
PAINTERLY_BLEND_MODES,
|
|
247
|
+
isBlendMode,
|
|
248
|
+
isPainterlyBlendMode,
|
|
249
|
+
mixPigment8,
|
|
250
|
+
mixPigments,
|
|
251
|
+
standardBlendMode
|
|
252
|
+
} from "../chunk-IRSTHLQQ.js";
|
|
253
|
+
import {
|
|
228
254
|
base64ToBytes,
|
|
229
255
|
bytesToBase64,
|
|
230
256
|
decodePng,
|
|
231
257
|
encodePng,
|
|
232
|
-
isBlendMode,
|
|
233
|
-
isPainterlyBlendMode,
|
|
234
258
|
isPng,
|
|
235
|
-
mixPigment8,
|
|
236
|
-
mixPigments,
|
|
237
259
|
parseDataUrl,
|
|
238
|
-
pngDataUrl
|
|
239
|
-
|
|
240
|
-
} from "../chunk-42TWUPNJ.js";
|
|
260
|
+
pngDataUrl
|
|
261
|
+
} from "../chunk-OTTT5N3K.js";
|
|
241
262
|
import {
|
|
242
263
|
TILE,
|
|
243
264
|
TiledSurface,
|
|
@@ -1305,7 +1326,7 @@ var PaintStrokeSession = class _PaintStrokeSession {
|
|
|
1305
1326
|
};
|
|
1306
1327
|
if (this.wetDriver) {
|
|
1307
1328
|
} 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 });
|
|
1329
|
+
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
1330
|
} else if (init.thick) {
|
|
1310
1331
|
const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
|
|
1311
1332
|
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 +1536,7 @@ var PaintStrokeSession = class _PaintStrokeSession {
|
|
|
1515
1536
|
const surface = changed ? new TiledSurface(ch, tiles, this.base.defaultValue) : null;
|
|
1516
1537
|
const dabs = this.dry ? this.dry.dabCount : this.thickDriver ? this.thickDriver.dabCount : this.stickerSpray ? this.stickerSpray.dabCount : this.wet.dabCount;
|
|
1517
1538
|
this.result = { layerId: this.layerId, bounds: changed ? this.bounds : null, dabs, strokeId: null };
|
|
1539
|
+
if (this.stickerSpray?.skipped.size) this.result.skippedStickers = [...this.stickerSpray.skipped];
|
|
1518
1540
|
const carried = this.wet?.load ?? this.thickDriver?.load;
|
|
1519
1541
|
if (carried) this.result.mixerLoad = this.init.brush.behavior.dirty ? carried : cleanMixer(carried);
|
|
1520
1542
|
this.host.commit(this, surface, false);
|
|
@@ -4161,10 +4183,16 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
4161
4183
|
wetOp = null;
|
|
4162
4184
|
/** The effects provider slot (see `setEffectsProvider`). */
|
|
4163
4185
|
effects = new EffectsSlot();
|
|
4186
|
+
/** The sticker library slot (see `setStickersProvider`). */
|
|
4187
|
+
stickers = new StickersSlot(editorStickers());
|
|
4188
|
+
stickerArt = new StickerArtCache();
|
|
4189
|
+
rasterizeSticker;
|
|
4164
4190
|
effectsRenderer = new PaintEffectsRenderer();
|
|
4165
4191
|
paperEffectNodeCache = null;
|
|
4166
4192
|
constructor(options = {}) {
|
|
4167
4193
|
this.historyLimit = Math.max(1, options.historyLimit ?? 200);
|
|
4194
|
+
this.rasterizeSticker = options.rasterizeSticker ?? defaultStickerRasterizer;
|
|
4195
|
+
if (options.stickers) this.stickers.set(options.stickers);
|
|
4168
4196
|
this.doc = createPaintDocument({ width: options.width, height: options.height, dpi: options.dpi, paper: this.resolvePaper(options.paper) });
|
|
4169
4197
|
this.userBrushes = (options.brushes ?? []).map((b) => normalizePaintBrush({ ...b, builtin: false }));
|
|
4170
4198
|
const start = this.findBrush(options.brushId ?? DEFAULT_BRUSH_ID) ?? this.findBrush(DEFAULT_BRUSH_ID);
|
|
@@ -5323,6 +5351,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
5323
5351
|
else delete next.builtin;
|
|
5324
5352
|
this.brush = next;
|
|
5325
5353
|
this.emit([]);
|
|
5354
|
+
if (next.engine === "sticker" && next.sticker.stamps.some((r) => !editorStampOf(r))) void this.prepareStickers(next.sticker.stamps).catch(() => this.emit([]));
|
|
5326
5355
|
return this.brush;
|
|
5327
5356
|
}
|
|
5328
5357
|
/** Saves the active brush (or `brush`) into the user library under `id` / `name`. */
|
|
@@ -5648,7 +5677,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
5648
5677
|
thick: brush.engine === "impasto" ? { channels: doc.thick?.[layer.id] ?? emptyThickChannels() } : void 0,
|
|
5649
5678
|
// Light paint: a twin of the stroke paints the light channel (laying, dimming, moving light).
|
|
5650
5679
|
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,
|
|
5680
|
+
sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc), art: this.stickerArt.get } : void 0,
|
|
5652
5681
|
paint: effect ? null : this.strokeGradient(init, brush, color),
|
|
5653
5682
|
effect
|
|
5654
5683
|
});
|
|
@@ -6445,9 +6474,19 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6445
6474
|
const stickers = {};
|
|
6446
6475
|
for (const [id, list] of Object.entries(ext.stickers)) {
|
|
6447
6476
|
if (!findLayer(state.layers, id) || !Array.isArray(list)) continue;
|
|
6448
|
-
const ok = list.
|
|
6477
|
+
const ok = list.flatMap((x) => {
|
|
6478
|
+
if (!x || typeof x.id !== "string" || !Number.isFinite(x.x) || !Number.isFinite(x.y) || !(x.size > 0)) return [];
|
|
6479
|
+
try {
|
|
6480
|
+
const ref2 = normalizeStickerRef(x.ref ?? x.stamp);
|
|
6481
|
+
const stamp = editorStampOf(ref2);
|
|
6482
|
+
const { stamp: _old, ...rest } = x;
|
|
6483
|
+
return [{ ...rest, ref: ref2, ...stamp ? { stamp } : {} }];
|
|
6484
|
+
} catch {
|
|
6485
|
+
return [];
|
|
6486
|
+
}
|
|
6487
|
+
});
|
|
6449
6488
|
if (ok.length !== list.length) problems.push(`Some stickers of layer "${id}" could not be read; they were dropped.`);
|
|
6450
|
-
stickers[id] = ok
|
|
6489
|
+
stickers[id] = ok;
|
|
6451
6490
|
}
|
|
6452
6491
|
if (Object.keys(stickers).length) state = { ...state, stickers };
|
|
6453
6492
|
}
|
|
@@ -6551,6 +6590,8 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6551
6590
|
delete this.extensions.paperEffect;
|
|
6552
6591
|
this.viewCompositor.clear();
|
|
6553
6592
|
this.emit();
|
|
6593
|
+
const refs = Object.values(this.doc.stickers ?? {}).flatMap((list) => list.map((x) => x.ref));
|
|
6594
|
+
if (refs.some((r) => !editorStampOf(r))) void this.prepareStickers(refs).catch(() => this.emit([]));
|
|
6554
6595
|
return loaded.problems;
|
|
6555
6596
|
}
|
|
6556
6597
|
/** Opens a saved document (clears the history). Returns what could not be read. */
|
|
@@ -6878,6 +6919,56 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6878
6919
|
if (!stickers) throw new PaintEditorError(`Layer "${l.name}" has no stickers; spray some with a sticker brush (list_brushes category sticker).`);
|
|
6879
6920
|
return { layer: l, stickers };
|
|
6880
6921
|
}
|
|
6922
|
+
// --- The sticker library ---------------------------------------------------------
|
|
6923
|
+
/** The sticker library: the editor's own stamps unless a host set its own. */
|
|
6924
|
+
get stickersProvider() {
|
|
6925
|
+
return this.stickers.provider;
|
|
6926
|
+
}
|
|
6927
|
+
/**
|
|
6928
|
+
* Sets the sticker library (`null` goes back to the editor's own stamps, `editorStickers()`);
|
|
6929
|
+
* to offer both, pass `combineStickerProviders([editorStickers(), yours])`. Loaded art is
|
|
6930
|
+
* forgotten. Not an edit: no undo step.
|
|
6931
|
+
*/
|
|
6932
|
+
setStickersProvider(provider) {
|
|
6933
|
+
if ((provider ?? this.stickers.fallback) === this.stickers.provider) return;
|
|
6934
|
+
this.stickers.set(provider);
|
|
6935
|
+
this.stickerArt.clear();
|
|
6936
|
+
this.emit([]);
|
|
6937
|
+
}
|
|
6938
|
+
/**
|
|
6939
|
+
* Loads the art of `refs` (provider stickers; editor stamps need none) so sprays and placements
|
|
6940
|
+
* can draw them. Rejects with a `PaintEditorError` naming an unknown ref and the closest known
|
|
6941
|
+
* ones, or a sticker whose art failed. Emits when art arrives, so views redraw.
|
|
6942
|
+
*/
|
|
6943
|
+
async prepareStickers(refs) {
|
|
6944
|
+
const list = [...new Set(refs.map((r) => this.readStickerRef(r)))].filter((r) => !editorStampOf(r));
|
|
6945
|
+
try {
|
|
6946
|
+
await Promise.all(list.map((r) => this.stickerArt.ensure(this.stickers.provider, r, this.rasterizeSticker)));
|
|
6947
|
+
} catch (e) {
|
|
6948
|
+
throw new PaintEditorError(e instanceof Error ? e.message : String(e));
|
|
6949
|
+
} finally {
|
|
6950
|
+
if (list.length) this.emit([]);
|
|
6951
|
+
}
|
|
6952
|
+
}
|
|
6953
|
+
/** Whether a sticker's art is ready to draw: `ready` (always for editor stamps), `loading`, `failed` (with why) or `none`. */
|
|
6954
|
+
stickerArtStatus(ref2) {
|
|
6955
|
+
return this.stickerArt.status(this.readStickerRef(ref2));
|
|
6956
|
+
}
|
|
6957
|
+
readStickerRef(ref2) {
|
|
6958
|
+
try {
|
|
6959
|
+
return normalizeStickerRef(ref2);
|
|
6960
|
+
} catch (e) {
|
|
6961
|
+
throw new PaintEditorError(e.message);
|
|
6962
|
+
}
|
|
6963
|
+
}
|
|
6964
|
+
/** Refuses to redraw stickers whose art has not loaded (they would vanish), naming them and what to call. */
|
|
6965
|
+
requireStickerArt(stickers) {
|
|
6966
|
+
const missing = [...new Set(stickers.filter((s) => !stickerStamp(s) && !this.stickerArt.get(s.ref)).map((s) => s.ref))];
|
|
6967
|
+
if (missing.length) {
|
|
6968
|
+
for (const r of missing) void this.stickerArt.ensure(this.stickers.provider, r, this.rasterizeSticker).then(() => this.emit([]), () => this.emit([]));
|
|
6969
|
+
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.`);
|
|
6970
|
+
}
|
|
6971
|
+
}
|
|
6881
6972
|
/** A layer's stickers, bottom first. */
|
|
6882
6973
|
listStickers(layerId) {
|
|
6883
6974
|
const id = layerId ?? this.doc.activeLayerId;
|
|
@@ -6891,6 +6982,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6891
6982
|
*/
|
|
6892
6983
|
commitStickers(label, layer, stickers, dirty) {
|
|
6893
6984
|
if (isLayerLocked(layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it first.`);
|
|
6985
|
+
this.requireStickerArt(stickers);
|
|
6894
6986
|
const before = this.previewBase() ?? this.doc;
|
|
6895
6987
|
this.stickerPreview = null;
|
|
6896
6988
|
const surface = this.redrawStickers(layer, stickers, dirty);
|
|
@@ -6899,7 +6991,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6899
6991
|
}
|
|
6900
6992
|
redrawStickers(layer, stickers, dirty) {
|
|
6901
6993
|
const partial = dirty && !layer.offset.x && !layer.offset.y;
|
|
6902
|
-
return partial ? stickerSurface(stickers, layer.surface, dirty) : stickerSurface(stickers);
|
|
6994
|
+
return partial ? stickerSurface(stickers, layer.surface, dirty, this.stickerArt.get) : stickerSurface(stickers, void 0, void 0, this.stickerArt.get);
|
|
6903
6995
|
}
|
|
6904
6996
|
/** The document from before the sticker preview on screen, or `null` when none is (anything else changed the document since). */
|
|
6905
6997
|
previewBase() {
|
|
@@ -6918,7 +7010,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6918
7010
|
const id = layerId ?? this.doc.activeLayerId;
|
|
6919
7011
|
if (!id) return null;
|
|
6920
7012
|
this.requireLayer(id);
|
|
6921
|
-
const hit = stickerAt(this.doc.stickers?.[id] ?? [], x, y);
|
|
7013
|
+
const hit = stickerAt(this.doc.stickers?.[id] ?? [], x, y, this.stickerArt.get);
|
|
6922
7014
|
return hit ? { ...hit } : null;
|
|
6923
7015
|
}
|
|
6924
7016
|
/** Picks a sticker for the panel and canvas (`null` for none). Editor state, not an undo step. */
|
|
@@ -6972,7 +7064,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6972
7064
|
*/
|
|
6973
7065
|
addStickers(layerId, input) {
|
|
6974
7066
|
const layer = this.wetLayer(layerId, "add stickers to");
|
|
6975
|
-
if (!input.length) throw new PaintEditorError("Pass at least one sticker (
|
|
7067
|
+
if (!input.length) throw new PaintEditorError("Pass at least one sticker (ref, x, y).");
|
|
6976
7068
|
if (input.length > MAX_ADD_STICKERS) throw new PaintEditorError(`At most ${MAX_ADD_STICKERS} stickers per call; split them over several calls.`);
|
|
6977
7069
|
const existing = this.doc.stickers?.[layer.id];
|
|
6978
7070
|
if (!existing?.length) {
|
|
@@ -6980,7 +7072,8 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6980
7072
|
}
|
|
6981
7073
|
let n = this.nextStickerNumber();
|
|
6982
7074
|
const added = input.map((raw, i) => {
|
|
6983
|
-
|
|
7075
|
+
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").`);
|
|
7076
|
+
for (const k of ["x", "y"]) if (raw[k] === void 0) throw new PaintEditorError(`Sticker ${i} needs ${k}.`);
|
|
6984
7077
|
let u;
|
|
6985
7078
|
try {
|
|
6986
7079
|
u = this.readStickerUpdate(raw);
|
|
@@ -8045,7 +8138,7 @@ function createPaintStickerTools(c) {
|
|
|
8045
8138
|
{
|
|
8046
8139
|
name: "list_stickers",
|
|
8047
8140
|
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.",
|
|
8141
|
+
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
8142
|
inputSchema: { type: "object", properties: { layerId: LAYER_ID }, additionalProperties: false },
|
|
8050
8143
|
annotations: { title: "List stickers", ...READ },
|
|
8051
8144
|
coordinates: { out: ["stickers[]"] },
|
|
@@ -8072,7 +8165,7 @@ function createPaintStickerTools(c) {
|
|
|
8072
8165
|
{
|
|
8073
8166
|
name: "add_stickers",
|
|
8074
8167
|
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.",
|
|
8168
|
+
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
8169
|
inputSchema: {
|
|
8077
8170
|
type: "object",
|
|
8078
8171
|
properties: {
|
|
@@ -8085,7 +8178,8 @@ function createPaintStickerTools(c) {
|
|
|
8085
8178
|
items: {
|
|
8086
8179
|
type: "object",
|
|
8087
8180
|
properties: {
|
|
8088
|
-
|
|
8181
|
+
ref: { type: "string", minLength: 1, description: "The sticker: a ref provider:id from find_stickers (e.g. editor:star). Give ref or stamp." },
|
|
8182
|
+
stamp: { type: "string", enum: [...STAMP_KINDS], description: "Older form: an editor stamp (same as ref editor:<stamp>)." },
|
|
8089
8183
|
x: { type: "number", description: "Centre x in document pixels." },
|
|
8090
8184
|
y: { type: "number", description: "Centre y in document pixels." },
|
|
8091
8185
|
size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels (default 48)." },
|
|
@@ -8094,7 +8188,7 @@ function createPaintStickerTools(c) {
|
|
|
8094
8188
|
opacity: { type: "number", minimum: 0, maximum: 1, description: "Opacity 0..1 (default 1)." },
|
|
8095
8189
|
seed: { type: "integer", minimum: 0, description: "Texture seed (default from the new id); splat and confetti shapes vary with it." }
|
|
8096
8190
|
},
|
|
8097
|
-
required: ["
|
|
8191
|
+
required: ["x", "y"],
|
|
8098
8192
|
additionalProperties: false
|
|
8099
8193
|
}
|
|
8100
8194
|
}
|
|
@@ -8104,7 +8198,14 @@ function createPaintStickerTools(c) {
|
|
|
8104
8198
|
},
|
|
8105
8199
|
annotations: { title: "Place stickers", ...WRITE },
|
|
8106
8200
|
coordinates: { in: ["stickers[]"], out: ["stickers[]"] },
|
|
8107
|
-
handler: ({ layerId, stickers }) =>
|
|
8201
|
+
handler: async ({ layerId, stickers }) => {
|
|
8202
|
+
const list = stickers;
|
|
8203
|
+
list.forEach((x, i) => {
|
|
8204
|
+
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").`);
|
|
8205
|
+
});
|
|
8206
|
+
await c.prepareStickers(list.map((x) => x.ref ?? `editor:${x.stamp}`));
|
|
8207
|
+
return { layerId: layerId ?? c.document.activeLayerId, stickers: c.addStickers(layerId, list) };
|
|
8208
|
+
}
|
|
8108
8209
|
},
|
|
8109
8210
|
{
|
|
8110
8211
|
name: "update_sticker",
|
|
@@ -8115,7 +8216,8 @@ function createPaintStickerTools(c) {
|
|
|
8115
8216
|
properties: {
|
|
8116
8217
|
layerId: LAYER_ID,
|
|
8117
8218
|
id: { type: "string", description: "Sticker id from list_stickers." },
|
|
8118
|
-
|
|
8219
|
+
ref: { type: "string", minLength: 1, description: "Another sticker: a ref provider:id from find_stickers." },
|
|
8220
|
+
stamp: { type: "string", enum: [...STAMP_KINDS], description: "Older form: another editor stamp (same as ref editor:<stamp>)." },
|
|
8119
8221
|
x: { type: "number", description: "Centre x in document pixels." },
|
|
8120
8222
|
y: { type: "number", description: "Centre y in document pixels." },
|
|
8121
8223
|
size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels." },
|
|
@@ -8128,7 +8230,11 @@ function createPaintStickerTools(c) {
|
|
|
8128
8230
|
},
|
|
8129
8231
|
annotations: { title: "Change a sticker", ...WRITE },
|
|
8130
8232
|
coordinates: { in: [""], out: [""] },
|
|
8131
|
-
handler: ({ layerId, id, ...update }) =>
|
|
8233
|
+
handler: async ({ layerId, id, ...update }) => {
|
|
8234
|
+
const refs = c.listStickers(layerId).map((s) => s.ref);
|
|
8235
|
+
await c.prepareStickers(update.ref ? [...refs, update.ref] : refs);
|
|
8236
|
+
return c.updateSticker(layerId, id, update);
|
|
8237
|
+
}
|
|
8132
8238
|
},
|
|
8133
8239
|
{
|
|
8134
8240
|
name: "arrange_stickers",
|
|
@@ -8145,7 +8251,10 @@ function createPaintStickerTools(c) {
|
|
|
8145
8251
|
additionalProperties: false
|
|
8146
8252
|
},
|
|
8147
8253
|
annotations: { title: "Bring stickers forward or back", ...WRITE },
|
|
8148
|
-
handler: ({ layerId, ids, to }) =>
|
|
8254
|
+
handler: async ({ layerId, ids, to }) => {
|
|
8255
|
+
await c.prepareStickers(c.listStickers(layerId).map((s) => s.ref));
|
|
8256
|
+
return { order: c.arrangeStickers(layerId, ids, to) };
|
|
8257
|
+
}
|
|
8149
8258
|
},
|
|
8150
8259
|
{
|
|
8151
8260
|
name: "remove_stickers",
|
|
@@ -8153,7 +8262,10 @@ function createPaintStickerTools(c) {
|
|
|
8153
8262
|
description: "Deletes stickers by id, or every sticker on the layer when ids is missing. One undo step. Returns the ids removed.",
|
|
8154
8263
|
inputSchema: { type: "object", properties: { layerId: LAYER_ID, ids: { type: "array", items: { type: "string", description: "Sticker id." }, description: "Sticker ids (default all)." } }, additionalProperties: false },
|
|
8155
8264
|
annotations: { title: "Delete stickers", ...DESTRUCTIVE },
|
|
8156
|
-
handler: ({ layerId, ids }) =>
|
|
8265
|
+
handler: async ({ layerId, ids }) => {
|
|
8266
|
+
await c.prepareStickers(c.listStickers(layerId).map((s) => s.ref));
|
|
8267
|
+
return { removed: c.removeStickers(layerId, ids) };
|
|
8268
|
+
}
|
|
8157
8269
|
}
|
|
8158
8270
|
];
|
|
8159
8271
|
}
|
|
@@ -9167,7 +9279,13 @@ var STICKER_BRUSH = {
|
|
|
9167
9279
|
type: "object",
|
|
9168
9280
|
description: "Sticker engine settings: stamps sprayed along the stroke as editable stickers. Missing fields keep their current values.",
|
|
9169
9281
|
properties: {
|
|
9170
|
-
stamps: {
|
|
9282
|
+
stamps: {
|
|
9283
|
+
type: "array",
|
|
9284
|
+
minItems: 1,
|
|
9285
|
+
maxItems: MAX_STICKER_STAMPS,
|
|
9286
|
+
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." },
|
|
9287
|
+
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.`
|
|
9288
|
+
},
|
|
9171
9289
|
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
9290
|
sizeJitter: { type: "number", minimum: 0, maximum: 1, description: "Random size change." },
|
|
9173
9291
|
rotationJitter: { type: "number", minimum: 0, maximum: 1, description: "Random turn as a fraction of \xB1180\xB0." },
|
|
@@ -9594,7 +9712,11 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
9594
9712
|
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
9713
|
inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brushes to start from." }, ...BRUSH_FIELDS }, additionalProperties: false },
|
|
9596
9714
|
annotations: { title: "Set the brush", ...SET4 },
|
|
9597
|
-
handler: (a) =>
|
|
9715
|
+
handler: async (a) => {
|
|
9716
|
+
const stamps = a.sticker?.stamps;
|
|
9717
|
+
if (stamps) await c.prepareStickers(stamps);
|
|
9718
|
+
return brushToJSON(c.setBrush(a));
|
|
9719
|
+
}
|
|
9598
9720
|
});
|
|
9599
9721
|
add({
|
|
9600
9722
|
name: "save_brush",
|
|
@@ -9770,6 +9892,9 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
9770
9892
|
coordinates: { in: ["points[]"], out: ["bounds"] },
|
|
9771
9893
|
handler: async (a) => {
|
|
9772
9894
|
await c.wetIdle();
|
|
9895
|
+
const base = a.brushId ? c.getBrush(a.brushId) : c.getState().brush;
|
|
9896
|
+
const over = a.brush;
|
|
9897
|
+
if ((over?.engine ?? base?.engine) === "sticker") await c.prepareStickers(over?.sticker?.stamps ?? base?.sticker.stamps ?? []);
|
|
9773
9898
|
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
9899
|
const r = await act({ kind: "stroke", stroke }, () => c.paintStroke(stroke));
|
|
9775
9900
|
return r.mixerLoad ? { ...r, mixerLoad: loadResult(r.mixerLoad) } : r;
|
|
@@ -10078,6 +10203,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
|
|
|
10078
10203
|
tools.push(...createPaintReplayTools(c));
|
|
10079
10204
|
tools.push(...createPaintStickerTools(c));
|
|
10080
10205
|
tools.push(...createPigmentTools());
|
|
10206
|
+
tools.push(...createStickerTools({ provider: () => c.stickersProvider }));
|
|
10081
10207
|
tools.push(
|
|
10082
10208
|
...createLayerEffectTools(
|
|
10083
10209
|
{
|
|
@@ -10251,7 +10377,7 @@ var PaintGesture = class {
|
|
|
10251
10377
|
}
|
|
10252
10378
|
const brush = this.controller.getState().brush;
|
|
10253
10379
|
const size = Math.min(2048, Math.max(2, Math.round(brush.tip.size)));
|
|
10254
|
-
const [added] = this.controller.addStickers(void 0, [{
|
|
10380
|
+
const [added] = this.controller.addStickers(void 0, [{ ref: brush.sticker.stamps[0] ?? "editor:star", x: round2(p.x), y: round2(p.y), size }]);
|
|
10255
10381
|
this.controller.selectSticker(added.id);
|
|
10256
10382
|
} catch (err) {
|
|
10257
10383
|
this.error = err instanceof Error ? err.message : String(err);
|
|
@@ -10787,6 +10913,15 @@ var RIBBON_PAIR_LABELS = { adjacent: "Neighbours", "first-last": "Outermost" };
|
|
|
10787
10913
|
var DOT_TEXTURE_ORDER_LABELS = { sequence: "In turn", random: "Random" };
|
|
10788
10914
|
var DOT_ROTATION_LABELS = { follow: "Follow motion", random: "Random", fixed: "Tip angle" };
|
|
10789
10915
|
var STAMP_LABELS = { dot: "Dot", star: "Star", heart: "Heart", leaf: "Leaf", flower: "Flower", confetti: "Confetti", splat: "Splat", sparkle: "Sparkle", ring: "Ring" };
|
|
10916
|
+
function toggleStickerRef(refs, ref2) {
|
|
10917
|
+
if (refs.includes(ref2)) return refs.length > 1 ? refs.filter((r) => r !== ref2) : [...refs];
|
|
10918
|
+
return refs.length < MAX_STICKER_STAMPS ? [...refs, ref2] : [...refs];
|
|
10919
|
+
}
|
|
10920
|
+
function stickerRefLabel(ref2) {
|
|
10921
|
+
const stamp = ref2.startsWith("editor:") ? ref2.slice(7) : null;
|
|
10922
|
+
if (stamp && STAMP_LABELS[stamp]) return STAMP_LABELS[stamp];
|
|
10923
|
+
return ref2.slice(ref2.indexOf(":") + 1);
|
|
10924
|
+
}
|
|
10790
10925
|
function toggleStamp(stamps, stamp) {
|
|
10791
10926
|
const next = stamps.includes(stamp) ? stamps.filter((s) => s !== stamp) : [...stamps, stamp];
|
|
10792
10927
|
return next.length ? next : [stamp];
|
|
@@ -11141,6 +11276,7 @@ export {
|
|
|
11141
11276
|
MAX_DOT_TEXTURES,
|
|
11142
11277
|
MAX_IMAGE_SIDE,
|
|
11143
11278
|
MAX_LIVE_EFFECT_SOURCES,
|
|
11279
|
+
MAX_STICKER_STAMPS,
|
|
11144
11280
|
MAX_ZOOM,
|
|
11145
11281
|
MIN_CANVAS_SIDE,
|
|
11146
11282
|
MIN_ZOOM,
|
|
@@ -11205,10 +11341,13 @@ export {
|
|
|
11205
11341
|
STAMP_LABELS,
|
|
11206
11342
|
STENCIL_KINDS,
|
|
11207
11343
|
STENCIL_SHAPES,
|
|
11344
|
+
STICKER_ART_SIZE,
|
|
11208
11345
|
STICKER_SLIDERS,
|
|
11209
11346
|
STROKE_SLIDERS,
|
|
11210
11347
|
SYMMETRY_MODES,
|
|
11211
11348
|
StencilSnapper,
|
|
11349
|
+
StickerArtCache,
|
|
11350
|
+
StickerBrowser,
|
|
11212
11351
|
StickerSpray,
|
|
11213
11352
|
TRACING_NODE_ID,
|
|
11214
11353
|
ThickStrokeDriver,
|
|
@@ -11256,6 +11395,7 @@ export {
|
|
|
11256
11395
|
decodeImageBlob,
|
|
11257
11396
|
defaultGuides,
|
|
11258
11397
|
defaultImageEncoder,
|
|
11398
|
+
defaultStickerRasterizer,
|
|
11259
11399
|
deserializePaintDocument,
|
|
11260
11400
|
deserializePaintDocumentAsync,
|
|
11261
11401
|
documentExtensions,
|
|
@@ -11374,6 +11514,7 @@ export {
|
|
|
11374
11514
|
rgbToHexColor,
|
|
11375
11515
|
rgbToHsl,
|
|
11376
11516
|
rgbToHsv,
|
|
11517
|
+
sampleArt,
|
|
11377
11518
|
sampleEffectAt,
|
|
11378
11519
|
sampleEffectField,
|
|
11379
11520
|
samplePressure,
|
|
@@ -11391,6 +11532,8 @@ export {
|
|
|
11391
11532
|
stencilOutline,
|
|
11392
11533
|
stickerAt,
|
|
11393
11534
|
stickerRect,
|
|
11535
|
+
stickerRefLabel,
|
|
11536
|
+
stickerStamp,
|
|
11394
11537
|
stickerSurface,
|
|
11395
11538
|
strokeBounds,
|
|
11396
11539
|
strokeDuration,
|
|
@@ -11408,6 +11551,7 @@ export {
|
|
|
11408
11551
|
toStrokePoint,
|
|
11409
11552
|
toggleDotTexture,
|
|
11410
11553
|
toggleStamp,
|
|
11554
|
+
toggleStickerRef,
|
|
11411
11555
|
translateStencil,
|
|
11412
11556
|
updatePaintGradientStop,
|
|
11413
11557
|
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[];
|