@pixerate/editor 0.277.0 → 0.278.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -368,7 +368,10 @@ require('../chunk-A6QWKBJP.cjs');
368
368
 
369
369
  var _chunkI3Y2Q3PMcjs = require('../chunk-I3Y2Q3PM.cjs');
370
370
  require('../chunk-MEGSQUQO.cjs');
371
- require('../chunk-MLLTWAXH.cjs');
371
+
372
+
373
+
374
+ var _chunkMLLTWAXHcjs = require('../chunk-MLLTWAXH.cjs');
372
375
  require('../chunk-SXQHWXEL.cjs');
373
376
 
374
377
 
@@ -4172,6 +4175,8 @@ function normalizeBrushStroke(raw) {
4172
4175
  points,
4173
4176
  seed: finite2(r.seed) ? r.seed | 0 : 0
4174
4177
  };
4178
+ const dual = r.dualColor === void 0 ? null : _chunkMLLTWAXHcjs.normalizeDualColor.call(void 0, r.dualColor);
4179
+ if (dual && /^#[0-9a-f]{6}$/.test(dual.light) && /^#[0-9a-f]{6}$/.test(dual.dark)) out.dualColor = dual;
4175
4180
  const copies = Array.isArray(r.copies) ? r.copies.map(readAffine).filter((m) => m !== null) : [];
4176
4181
  if (copies.length) out.copies = copies;
4177
4182
  const load = readLoad(r.load);
@@ -4380,9 +4385,77 @@ function serializePaintDocument(state, options = {}) {
4380
4385
  const { layers, assets } = _chunkQBZEC2JJcjs.serializeLayers.call(void 0, state.layers);
4381
4386
  return { ...header(state, options), layers, assets };
4382
4387
  }
4388
+ var NO_EXTENSION_PNGS = /* @__PURE__ */ new Set(["format", "version", "width", "height", "dpi", "paper", "layers", "assets", "activeLayerId", "strokes", "wetEvents", "paintEvents", "origin"]);
4389
+ var EXTENSION_ASSET_REF = "asset:";
4390
+ var PNG_DATA_URL = "data:image/png;base64,";
4391
+ var storedPngs = /* @__PURE__ */ new WeakMap();
4392
+ function fnv1a(text) {
4393
+ let h = 2166136261;
4394
+ for (let i = 0; i < text.length; i++) {
4395
+ h ^= text.charCodeAt(i);
4396
+ h = Math.imul(h, 16777619);
4397
+ }
4398
+ return (h >>> 0).toString(16).padStart(8, "0");
4399
+ }
4400
+ async function externalizePngs(value, assets, store) {
4401
+ if (typeof value === "string") {
4402
+ if (!value.startsWith(PNG_DATA_URL)) return value;
4403
+ const id = `ext-${fnv1a(value)}-${value.length.toString(36)}`;
4404
+ if (!assets[id]) {
4405
+ let refs = storedPngs.get(store);
4406
+ if (!refs) storedPngs.set(store, refs = /* @__PURE__ */ new Map());
4407
+ let ref2 = refs.get(value);
4408
+ if (!ref2) {
4409
+ const parsed = _chunkW5M3J7PVcjs.parseDataUrl.call(void 0, value);
4410
+ if (!parsed) return value;
4411
+ const b = parsed.bytes;
4412
+ const u32 = (o) => (b[o] << 24 | b[o + 1] << 16 | b[o + 2] << 8 | b[o + 3]) >>> 0;
4413
+ ref2 = await store.put(new Blob([b], { type: "image/png" }), { id, width: b.length >= 24 ? u32(16) : 0, height: b.length >= 24 ? u32(20) : 0 });
4414
+ if (typeof ref2 !== "string" || !ref2) throw new Error(`The asset store returned no reference for "${id}".`);
4415
+ refs.set(value, ref2);
4416
+ }
4417
+ assets[id] = ref2;
4418
+ }
4419
+ return `${EXTENSION_ASSET_REF}${id}`;
4420
+ }
4421
+ if (Array.isArray(value)) {
4422
+ const out = [];
4423
+ for (const v of value) out.push(await externalizePngs(v, assets, store));
4424
+ return out;
4425
+ }
4426
+ if (value && typeof value === "object") {
4427
+ const out = {};
4428
+ for (const [k, v] of Object.entries(value)) out[k] = await externalizePngs(v, assets, store);
4429
+ return out;
4430
+ }
4431
+ return value;
4432
+ }
4433
+ function inlinePngs(value, assets, problems, field, used) {
4434
+ if (typeof value === "string") {
4435
+ if (!value.startsWith(EXTENSION_ASSET_REF)) return value;
4436
+ const id = value.slice(EXTENSION_ASSET_REF.length);
4437
+ const url = assets[id];
4438
+ if (typeof url === "string" && url.startsWith("data:")) {
4439
+ used.add(id);
4440
+ return url;
4441
+ }
4442
+ const msg = `"${field}" refers to asset "${id}", which could not be read; that part loads empty.`;
4443
+ if (!problems.includes(msg)) problems.push(msg);
4444
+ return value;
4445
+ }
4446
+ if (Array.isArray(value)) return value.map((v) => inlinePngs(v, assets, problems, field, used));
4447
+ if (value && typeof value === "object") {
4448
+ const out = {};
4449
+ for (const [k, v] of Object.entries(value)) out[k] = inlinePngs(v, assets, problems, field, used);
4450
+ return out;
4451
+ }
4452
+ return value;
4453
+ }
4383
4454
  async function serializePaintDocumentExternal(state, store, options = {}) {
4384
4455
  const { layers, assets } = await _chunkQBZEC2JJcjs.serializeLayersExternal.call(void 0, state.layers, store);
4385
- return { ...header(state, options), layers, assets };
4456
+ const out = { ...header(state, options), layers, assets };
4457
+ for (const key of Object.keys(out)) if (!NO_EXTENSION_PNGS.has(key)) out[key] = await externalizePngs(out[key], assets, store);
4458
+ return out;
4386
4459
  }
4387
4460
  function paintLayersOnly(layers, problems) {
4388
4461
  const out = [];
@@ -4415,9 +4488,15 @@ function deserializePaintDocument(raw) {
4415
4488
  throw new Error(`Paint document version ${JSON.stringify(r.version)} is newer than this editor reads (${PAINT_SCHEMA_VERSION}); update @pixerate/editor.`);
4416
4489
  }
4417
4490
  const problems = [];
4491
+ const rawAssets = r.assets && typeof r.assets === "object" ? r.assets : {};
4492
+ const used = /* @__PURE__ */ new Set();
4493
+ const inlined = { ...r };
4494
+ for (const key of Object.keys(r)) if (!NO_EXTENSION_PNGS.has(key)) inlined[key] = inlinePngs(r[key], rawAssets, problems, key, used);
4495
+ return readDocument(inlined, Object.fromEntries(Object.entries(rawAssets).filter(([id]) => !used.has(id))), problems);
4496
+ }
4497
+ function readDocument(r, assets, problems) {
4418
4498
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
4419
4499
  const paper = _chunkPEQWARCPcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
4420
- const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
4421
4500
  const layers = paintLayersOnly(_chunkQBZEC2JJcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
4422
4501
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
4423
4502
  const activeLayerId = wanted && _chunkPVJMTLPJcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkPVJMTLPJcjs.flattenLayers.call(void 0, layers), 'access', _184 => _184.filter, 'call', _185 => _185((l) => l.type === "pixel"), 'access', _186 => _186.pop, 'call', _187 => _187(), 'optionalAccess', _188 => _188.id]), () => ( null));
@@ -6991,7 +7070,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
6991
7070
  __init157() {this.tempLayerTargets = /* @__PURE__ */ new Map()}
6992
7071
  __init158() {this.answeringMutation = false}
6993
7072
  __init159() {this.lastMutationTick = null}
6994
- constructor(options = {}) {;_class17.prototype.__init77.call(this);_class17.prototype.__init78.call(this);_class17.prototype.__init79.call(this);_class17.prototype.__init80.call(this);_class17.prototype.__init81.call(this);_class17.prototype.__init82.call(this);_class17.prototype.__init83.call(this);_class17.prototype.__init84.call(this);_class17.prototype.__init85.call(this);_class17.prototype.__init86.call(this);_class17.prototype.__init87.call(this);_class17.prototype.__init88.call(this);_class17.prototype.__init89.call(this);_class17.prototype.__init90.call(this);_class17.prototype.__init91.call(this);_class17.prototype.__init92.call(this);_class17.prototype.__init93.call(this);_class17.prototype.__init94.call(this);_class17.prototype.__init95.call(this);_class17.prototype.__init96.call(this);_class17.prototype.__init97.call(this);_class17.prototype.__init98.call(this);_class17.prototype.__init99.call(this);_class17.prototype.__init100.call(this);_class17.prototype.__init101.call(this);_class17.prototype.__init102.call(this);_class17.prototype.__init103.call(this);_class17.prototype.__init104.call(this);_class17.prototype.__init105.call(this);_class17.prototype.__init106.call(this);_class17.prototype.__init107.call(this);_class17.prototype.__init108.call(this);_class17.prototype.__init109.call(this);_class17.prototype.__init110.call(this);_class17.prototype.__init111.call(this);_class17.prototype.__init112.call(this);_class17.prototype.__init113.call(this);_class17.prototype.__init114.call(this);_class17.prototype.__init115.call(this);_class17.prototype.__init116.call(this);_class17.prototype.__init117.call(this);_class17.prototype.__init118.call(this);_class17.prototype.__init119.call(this);_class17.prototype.__init120.call(this);_class17.prototype.__init121.call(this);_class17.prototype.__init122.call(this);_class17.prototype.__init123.call(this);_class17.prototype.__init124.call(this);_class17.prototype.__init125.call(this);_class17.prototype.__init126.call(this);_class17.prototype.__init127.call(this);_class17.prototype.__init128.call(this);_class17.prototype.__init129.call(this);_class17.prototype.__init130.call(this);_class17.prototype.__init131.call(this);_class17.prototype.__init132.call(this);_class17.prototype.__init133.call(this);_class17.prototype.__init134.call(this);_class17.prototype.__init135.call(this);_class17.prototype.__init136.call(this);_class17.prototype.__init137.call(this);_class17.prototype.__init138.call(this);_class17.prototype.__init139.call(this);_class17.prototype.__init140.call(this);_class17.prototype.__init141.call(this);_class17.prototype.__init142.call(this);_class17.prototype.__init143.call(this);_class17.prototype.__init144.call(this);_class17.prototype.__init145.call(this);_class17.prototype.__init146.call(this);_class17.prototype.__init147.call(this);_class17.prototype.__init148.call(this);_class17.prototype.__init149.call(this);_class17.prototype.__init150.call(this);_class17.prototype.__init151.call(this);_class17.prototype.__init152.call(this);_class17.prototype.__init153.call(this);_class17.prototype.__init154.call(this);_class17.prototype.__init155.call(this);_class17.prototype.__init156.call(this);_class17.prototype.__init157.call(this);_class17.prototype.__init158.call(this);_class17.prototype.__init159.call(this);_class17.prototype.__init160.call(this);_class17.prototype.__init161.call(this);_class17.prototype.__init162.call(this);_class17.prototype.__init163.call(this);_class17.prototype.__init164.call(this);_class17.prototype.__init165.call(this);_class17.prototype.__init166.call(this);
7073
+ constructor(options = {}) {;_class17.prototype.__init77.call(this);_class17.prototype.__init78.call(this);_class17.prototype.__init79.call(this);_class17.prototype.__init80.call(this);_class17.prototype.__init81.call(this);_class17.prototype.__init82.call(this);_class17.prototype.__init83.call(this);_class17.prototype.__init84.call(this);_class17.prototype.__init85.call(this);_class17.prototype.__init86.call(this);_class17.prototype.__init87.call(this);_class17.prototype.__init88.call(this);_class17.prototype.__init89.call(this);_class17.prototype.__init90.call(this);_class17.prototype.__init91.call(this);_class17.prototype.__init92.call(this);_class17.prototype.__init93.call(this);_class17.prototype.__init94.call(this);_class17.prototype.__init95.call(this);_class17.prototype.__init96.call(this);_class17.prototype.__init97.call(this);_class17.prototype.__init98.call(this);_class17.prototype.__init99.call(this);_class17.prototype.__init100.call(this);_class17.prototype.__init101.call(this);_class17.prototype.__init102.call(this);_class17.prototype.__init103.call(this);_class17.prototype.__init104.call(this);_class17.prototype.__init105.call(this);_class17.prototype.__init106.call(this);_class17.prototype.__init107.call(this);_class17.prototype.__init108.call(this);_class17.prototype.__init109.call(this);_class17.prototype.__init110.call(this);_class17.prototype.__init111.call(this);_class17.prototype.__init112.call(this);_class17.prototype.__init113.call(this);_class17.prototype.__init114.call(this);_class17.prototype.__init115.call(this);_class17.prototype.__init116.call(this);_class17.prototype.__init117.call(this);_class17.prototype.__init118.call(this);_class17.prototype.__init119.call(this);_class17.prototype.__init120.call(this);_class17.prototype.__init121.call(this);_class17.prototype.__init122.call(this);_class17.prototype.__init123.call(this);_class17.prototype.__init124.call(this);_class17.prototype.__init125.call(this);_class17.prototype.__init126.call(this);_class17.prototype.__init127.call(this);_class17.prototype.__init128.call(this);_class17.prototype.__init129.call(this);_class17.prototype.__init130.call(this);_class17.prototype.__init131.call(this);_class17.prototype.__init132.call(this);_class17.prototype.__init133.call(this);_class17.prototype.__init134.call(this);_class17.prototype.__init135.call(this);_class17.prototype.__init136.call(this);_class17.prototype.__init137.call(this);_class17.prototype.__init138.call(this);_class17.prototype.__init139.call(this);_class17.prototype.__init140.call(this);_class17.prototype.__init141.call(this);_class17.prototype.__init142.call(this);_class17.prototype.__init143.call(this);_class17.prototype.__init144.call(this);_class17.prototype.__init145.call(this);_class17.prototype.__init146.call(this);_class17.prototype.__init147.call(this);_class17.prototype.__init148.call(this);_class17.prototype.__init149.call(this);_class17.prototype.__init150.call(this);_class17.prototype.__init151.call(this);_class17.prototype.__init152.call(this);_class17.prototype.__init153.call(this);_class17.prototype.__init154.call(this);_class17.prototype.__init155.call(this);_class17.prototype.__init156.call(this);_class17.prototype.__init157.call(this);_class17.prototype.__init158.call(this);_class17.prototype.__init159.call(this);_class17.prototype.__init160.call(this);_class17.prototype.__init161.call(this);_class17.prototype.__init162.call(this);_class17.prototype.__init163.call(this);_class17.prototype.__init164.call(this);_class17.prototype.__init165.call(this);_class17.prototype.__init166.call(this);_class17.prototype.__init167.call(this);_class17.prototype.__init168.call(this);_class17.prototype.__init169.call(this);
6995
7074
  this.historyLimit = Math.max(1, _nullishCoalesce(options.historyLimit, () => ( 200)));
6996
7075
  this.rasterizeSticker = _nullishCoalesce(options.rasterizeSticker, () => ( defaultStickerRasterizer));
6997
7076
  if (options.stickers) this.stickers.set(options.stickers);
@@ -9025,7 +9104,8 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9025
9104
  __init163() {this.brushColour = null}
9026
9105
  /**
9027
9106
  * The host's colour scheme: a paint colour that came from a brush's light / dark default
9028
- * resolves to the new side. Editor state, not an undo step.
9107
+ * resolves to the new side, and stroke layers show their dual-colour strokes in it. Only the
9108
+ * view changes: the document, history and change listeners don't hear of it.
9029
9109
  */
9030
9110
  setColorScheme(scheme) {
9031
9111
  const next = scheme === "dark" ? "dark" : "light";
@@ -9033,9 +9113,77 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9033
9113
  this.colorScheme = next;
9034
9114
  const hex2 = this.brushColour ? _chunkJBZRVLXVcjs.brushColourHex.call(void 0, this.brushColour, next) : null;
9035
9115
  if (hex2) this.color = hex2;
9116
+ this.liveLayers = null;
9036
9117
  const refs = _chunkPEQWARCPcjs.brushStickerRefs.call(void 0, this.brush);
9037
9118
  if (refs.some((r) => !_chunkRDFHWAHLcjs.editorStampOf.call(void 0, r))) void this.prepareStickers(refs).catch(() => this.emit([]));
9038
- this.emit([]);
9119
+ this.emit();
9120
+ }
9121
+ /**
9122
+ * Stroke layers in the colour scheme: the document keeps every stroke layer drawn with each
9123
+ * stroke's `color` (a dual-colour stroke's light side), so saved and shared documents never
9124
+ * depend on who is looking. The view (display, image exports, the base a pointer stroke paints
9125
+ * on) draws dual-colour strokes in the scheme's side instead. One cached surface per layer,
9126
+ * brought up to date from the strokes that changed since it was drawn.
9127
+ */
9128
+ __init164() {this.schemeViews = /* @__PURE__ */ new Map()}
9129
+ __init165() {this.schemeCopies = /* @__PURE__ */ new WeakMap()}
9130
+ /** Set while a stroke is painted for the document rather than the view (`runStroke` on a stroke layer): dual colours take this side. */
9131
+ __init166() {this.paintScheme = null}
9132
+ /** A stroke as the scheme shows it: itself, or (a dual-colour stroke) a copy in the scheme's side. */
9133
+ schemeStroke(st, scheme) {
9134
+ const want = _optionalChain([st, 'access', _551 => _551.dualColor, 'optionalAccess', _552 => _552[scheme]]);
9135
+ if (!want || want === st.color) return st;
9136
+ const had = this.schemeCopies.get(st);
9137
+ if (_optionalChain([had, 'optionalAccess', _553 => _553.scheme]) === scheme) return had.stroke;
9138
+ const out = { ...st, color: want };
9139
+ if (st.load) {
9140
+ const load = brushLoadForStroke(st.brush, _chunkIFWLZZCWcjs.EMPTY_MIXER_LOAD, _chunkPEQWARCPcjs.hexToRgb8.call(void 0, want).map((v) => v / 255));
9141
+ if (load.reservoir || load.pickup) out.load = load;
9142
+ else delete out.load;
9143
+ }
9144
+ this.schemeCopies.set(st, { scheme, stroke: out });
9145
+ return out;
9146
+ }
9147
+ /** A stroke layer's surface in the scheme, or `null` when the document's pixels already show it. */
9148
+ schemeSurface(layer, list) {
9149
+ const scheme = this.colorScheme;
9150
+ if (!list.some((st) => st.dualColor && st.dualColor[scheme] !== st.color)) {
9151
+ this.schemeViews.delete(layer.id);
9152
+ return null;
9153
+ }
9154
+ const had = this.schemeViews.get(layer.id);
9155
+ if (had && had.scheme === scheme && had.list === list && had.base === layer.surface) return had.surface;
9156
+ const view = list.map((st) => this.schemeStroke(st, scheme));
9157
+ let surface;
9158
+ if (had && had.scheme === scheme && had.list !== list && !layer.offset.x && !layer.offset.y) {
9159
+ const now = new Set(list);
9160
+ const before = new Set(had.list);
9161
+ const gone = had.list.filter((st) => !now.has(st));
9162
+ const kept = list.filter((st) => before.has(st));
9163
+ const sameOrder = kept.every((st, i) => st === had.list.filter((x) => now.has(x))[i]);
9164
+ surface = sameOrder ? this.drawLiveStrokes({ ...layer, surface: had.surface }, view, this.strokeAreas(gone.map((st) => this.schemeStroke(st, scheme)))) : this.drawLiveStrokes(layer, view);
9165
+ } else surface = this.drawLiveStrokes(layer, view);
9166
+ this.schemeViews.set(layer.id, { scheme, list, base: layer.surface, surface });
9167
+ return surface;
9168
+ }
9169
+ /** `layers` with each stroke layer that holds dual-colour strokes shown in the scheme. */
9170
+ schemeLayers(layers) {
9171
+ const live = this.doc.liveStrokes;
9172
+ if (!live) return layers;
9173
+ let out = layers;
9174
+ for (const [id, list] of Object.entries(live)) {
9175
+ const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, out, id), 'optionalAccess', _554 => _554.layer]);
9176
+ if (!isPixelLayer(l)) continue;
9177
+ const surface = this.schemeSurface(l, list);
9178
+ if (surface) out = _chunkPVJMTLPJcjs.mapLayer.call(void 0, out, id, () => ({ ...l, surface }));
9179
+ }
9180
+ return out;
9181
+ }
9182
+ /** The paint colour's light / dark pair for a stroke with `brushId`, when the colour came from one (a brush's own or default colour, or `setColor`). */
9183
+ dualPaint(brushId) {
9184
+ const spec = brushId !== void 0 ? _optionalChain([this, 'access', _555 => _555.findEntry, 'call', _556 => _556(brushId), 'optionalAccess', _557 => _557.spec]) : this.brushSpec;
9185
+ if (_optionalChain([spec, 'optionalAccess', _558 => _558.colour, 'optionalAccess', _559 => _559.own]) && spec.colour.default !== void 0) return dualHex(spec.colour.default);
9186
+ return this.brushColour ? dualHex(this.brushColour) : null;
9039
9187
  }
9040
9188
  /** Locks the paint colour: choosing a brush with a default colour keeps it. Editor state, not an undo step. */
9041
9189
  setColorLocked(locked) {
@@ -9050,7 +9198,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9050
9198
  */
9051
9199
  takeBrushColour(spec) {
9052
9200
  if (this.colorLocked) return;
9053
- const d = _optionalChain([spec, 'access', _551 => _551.colour, 'optionalAccess', _552 => _552.default]);
9201
+ const d = _optionalChain([spec, 'access', _560 => _560.colour, 'optionalAccess', _561 => _561.default]);
9054
9202
  const hex2 = d !== void 0 ? _chunkJBZRVLXVcjs.brushColourHex.call(void 0, d, this.colorScheme) : null;
9055
9203
  if (!hex2) return;
9056
9204
  this.color = hex2;
@@ -9061,14 +9209,20 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9061
9209
  }
9062
9210
  /** A brush that always paints its own colour (`colour.own`): that colour, resolved for the scheme now; else `null`. */
9063
9211
  ownColour(brushId) {
9064
- const spec = brushId !== void 0 ? _optionalChain([this, 'access', _553 => _553.findEntry, 'call', _554 => _554(brushId), 'optionalAccess', _555 => _555.spec]) : this.brushSpec;
9065
- const d = _optionalChain([spec, 'optionalAccess', _556 => _556.colour, 'optionalAccess', _557 => _557.own]) ? spec.colour.default : void 0;
9212
+ const spec = brushId !== void 0 ? _optionalChain([this, 'access', _562 => _562.findEntry, 'call', _563 => _563(brushId), 'optionalAccess', _564 => _564.spec]) : this.brushSpec;
9213
+ const d = _optionalChain([spec, 'optionalAccess', _565 => _565.colour, 'optionalAccess', _566 => _566.own]) ? spec.colour.default : void 0;
9066
9214
  return d !== void 0 ? _chunkJBZRVLXVcjs.brushColourHex.call(void 0, d, this.colorScheme) : null;
9067
9215
  }
9068
- /** Sets the paint colour (and goes back to one colour from gradient paint). */
9216
+ /**
9217
+ * Sets the paint colour (and goes back to one colour from gradient paint). A light / dark pair
9218
+ * paints the colour scheme's side, follows `setColorScheme`, and is recorded with each stroke
9219
+ * painted in it. Returns the colour as #rrggbb.
9220
+ */
9069
9221
  setColor(color) {
9070
- this.color = parseColor(color);
9071
- this.brushColour = null;
9222
+ const dual = typeof color === "string" ? null : dualHex(color);
9223
+ if (typeof color !== "string" && !dual) throw new PaintEditorError(`color ${JSON.stringify(color)} is not a colour; use #rrggbb, or { light, dark } with a colour each.`);
9224
+ this.color = dual ? dual[this.colorScheme] : parseColor(color);
9225
+ this.brushColour = dual;
9072
9226
  this.gradient = null;
9073
9227
  this.effectPaint = this.effectPaintPending = null;
9074
9228
  this.paintEpoch++;
@@ -9197,11 +9351,20 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9197
9351
  strokeCopies() {
9198
9352
  return symmetryCopies(this.guides.symmetry);
9199
9353
  }
9200
- sessionFor(doc, init, host, points) {
9354
+ sessionFor(doc, given, host, points) {
9355
+ let dualColor = null;
9356
+ if (given.color !== void 0 && typeof given.color !== "string") {
9357
+ dualColor = dualHex(given.color);
9358
+ if (!dualColor) throw new PaintEditorError(`color ${JSON.stringify(given.color)} is not a colour; use #rrggbb, or { light, dark } with a colour each.`);
9359
+ }
9360
+ const scheme = _nullishCoalesce(this.paintScheme, () => ( this.colorScheme));
9361
+ let init = dualColor ? { ...given, color: dualColor[scheme] } : given;
9201
9362
  if (init.paint !== void 0 && !_chunkPEQWARCPcjs.isPaintEffectPaint.call(void 0, init.paint)) {
9202
9363
  const p = this.readStrokePaint(init.paint);
9203
- if (p.type === "color") init = { ...init, color: p.color, paint: void 0 };
9204
- else init = { ...init, paint: p };
9364
+ if (p.type === "color") {
9365
+ init = { ...init, color: p.color, paint: void 0 };
9366
+ dualColor = null;
9367
+ } else init = { ...init, paint: p };
9205
9368
  }
9206
9369
  let layer = (() => {
9207
9370
  const id = _nullishCoalesce(init.layerId, () => ( doc.activeLayerId));
@@ -9226,17 +9389,17 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9226
9389
  if (brush.behavior.multicolor.mode !== "off") throw new PaintEditorError(`Ghost paint (${brush.name}) needs a single colour to subtract as it fades, so it can't use multi-colour paint; set behavior.multicolor.mode to "off" (set_brush).`);
9227
9390
  const gCol = init.color === void 0 ? _nullishCoalesce(this.ownColour(init.brushId), () => ( this.color)) : parseColor(init.color);
9228
9391
  if (this.strokeGradient(init, brush, gCol)) throw new PaintEditorError(`Ghost paint (${brush.name}) needs a single colour to subtract as it fades, so it can't paint a gradient; set a solid colour (set_color) or pass color to paint_stroke.`);
9229
- if (Boolean(_optionalChain([doc, 'access', _558 => _558.light, 'optionalAccess', _559 => _559[layer.id], 'optionalAccess', _560 => _560.tiles, 'access', _561 => _561.size])) || Boolean(_optionalChain([this, 'access', _562 => _562.wet, 'access', _563 => _563.world, 'optionalAccess', _564 => _564.hasLane, 'call', _565 => _565(layer.id)]) && this.wet.world.isLit(layer.id))) {
9392
+ if (Boolean(_optionalChain([doc, 'access', _567 => _567.light, 'optionalAccess', _568 => _568[layer.id], 'optionalAccess', _569 => _569.tiles, 'access', _570 => _570.size])) || Boolean(_optionalChain([this, 'access', _571 => _571.wet, 'access', _572 => _572.world, 'optionalAccess', _573 => _573.hasLane, 'call', _574 => _574(layer.id)]) && this.wet.world.isLit(layer.id))) {
9230
9393
  throw new PaintEditorError(`Layer "${layer.name}" holds light paint, and ghost paint shares the wet light channel; paint on another layer (add_layer) or clear the light first (clear_light).`);
9231
9394
  }
9232
9395
  }
9233
9396
  const effect = this.strokeEffect(init, brush, points);
9234
- if (!points && init.paint === void 0 && _optionalChain([effect, 'optionalAccess', _566 => _566.source, 'access', _567 => _567.map, 'optionalAccess', _568 => _568.by]) === "path" && _chunkHRUK5TFWcjs.isWetBrush.call(void 0, brush)) {
9397
+ if (!points && init.paint === void 0 && _optionalChain([effect, 'optionalAccess', _575 => _575.source, 'access', _576 => _576.map, 'optionalAccess', _577 => _577.by]) === "path" && _chunkHRUK5TFWcjs.isWetBrush.call(void 0, brush)) {
9235
9398
  throw new PaintEditorError(`The ${brush.name} brush paints wet media, which can't follow a path that isn't known until the stroke ends; paint with a dry brush, set_effect_paint with by: "stroke", or give the points to paint_stroke.`);
9236
9399
  }
9237
9400
  if (brush.light.amount > 0) {
9238
9401
  if (brush.engine === "sticker") throw new PaintEditorError(`The ${brush.name} brush sprays stickers, which don't take light yet; paint light with a dab or particle light brush (glow-gel, neon-marker; list_brush_presets lists them), or set light.amount to 0 (set_brush).`);
9239
- if (Boolean(_optionalChain([this, 'access', _569 => _569.wet, 'access', _570 => _570.world, 'optionalAccess', _571 => _571.hasLane, 'call', _572 => _572(layer.id)]) && this.wet.world.getGhost(layer.id)) || Boolean(_optionalChain([this, 'access', _573 => _573.wet, 'access', _574 => _574.settings, 'access', _575 => _575.get, 'call', _576 => _576(layer.id), 'optionalAccess', _577 => _577.ghost]))) {
9402
+ if (Boolean(_optionalChain([this, 'access', _578 => _578.wet, 'access', _579 => _579.world, 'optionalAccess', _580 => _580.hasLane, 'call', _581 => _581(layer.id)]) && this.wet.world.getGhost(layer.id)) || Boolean(_optionalChain([this, 'access', _582 => _582.wet, 'access', _583 => _583.settings, 'access', _584 => _584.get, 'call', _585 => _585(layer.id), 'optionalAccess', _586 => _586.ghost]))) {
9240
9403
  throw new PaintEditorError(`Layer "${layer.name}" has ghost paint fading on it, which uses the wet light channel; paint light on another layer (add_layer), or finish the ghost first (dry_paint).`);
9241
9404
  }
9242
9405
  }
@@ -9250,18 +9413,18 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9250
9413
  if (brush.engine === "sticker") throw new PaintEditorError(`Sticker brushes spray objects and cannot lay ferrofluid (${brush.name}); paint ferrofluid with a dab or particle brush (ferrofluid, ferro-ink; list_brush_presets lists them), or set ferro.amount to 0 (set_brush).`);
9251
9414
  if (brush.engine === "wet") throw new PaintEditorError(`Wet brushes cannot lay ferrofluid (${brush.name}); paint ferrofluid with a dry or impasto brush (ferrofluid, ferro-ink), or set ferro.amount to 0 (set_brush).`);
9252
9415
  }
9253
- if (_optionalChain([doc, 'access', _578 => _578.liveStrokes, 'optionalAccess', _579 => _579[layer.id]])) {
9416
+ if (_optionalChain([doc, 'access', _587 => _587.liveStrokes, 'optionalAccess', _588 => _588[layer.id]])) {
9254
9417
  const why = liveStrokeRefusal(brush);
9255
9418
  if (why) throw new PaintEditorError(`Layer "${layer.name}" is a stroke layer. ${why}`);
9256
9419
  }
9257
- if (_optionalChain([doc, 'access', _580 => _580.liveStrokes, 'optionalAccess', _581 => _581[layer.id]]) && _optionalChain([effect, 'optionalAccess', _582 => _582.source, 'access', _583 => _583.live])) {
9420
+ if (_optionalChain([doc, 'access', _589 => _589.liveStrokes, 'optionalAccess', _590 => _590[layer.id]]) && _optionalChain([effect, 'optionalAccess', _591 => _591.source, 'access', _592 => _592.live])) {
9258
9421
  const key = _chunkPEQWARCPcjs.effectPaintKey.call(void 0, effect.source);
9259
9422
  const { sources } = this.liveEffects(doc);
9260
9423
  if (!sources.some((p) => _chunkPEQWARCPcjs.effectPaintKey.call(void 0, p) === key) && sources.length >= MAX_LIVE_EFFECT_SOURCES) {
9261
9424
  throw new PaintEditorError(`The painting already plays ${MAX_LIVE_EFFECT_SOURCES} live effects, the most it can; paint with one of them, or set_effect_paint with live false to bake this one.`);
9262
9425
  }
9263
9426
  }
9264
- const stickerLayer = Boolean(_optionalChain([doc, 'access', _584 => _584.stickers, 'optionalAccess', _585 => _585[layer.id], 'optionalAccess', _586 => _586.length]));
9427
+ const stickerLayer = Boolean(_optionalChain([doc, 'access', _593 => _593.stickers, 'optionalAccess', _594 => _594[layer.id], 'optionalAccess', _595 => _595.length]));
9265
9428
  if (brush.engine === "sticker") {
9266
9429
  if (!stickerLayer && _chunk474IQG74cjs.contentBounds.call(void 0, layer.surface)) throw new PaintEditorError(`Layer "${layer.name}" already has paint; spray stickers onto an empty layer (add_layer) so they stay editable.`);
9267
9430
  } else if (stickerLayer) {
@@ -9275,12 +9438,12 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9275
9438
  const oy = layer.offset.y;
9276
9439
  const moved = { ...layer, surface: _chunk474IQG74cjs.translateSurface.call(void 0, layer.surface, ox, oy), offset: { x: 0, y: 0 } };
9277
9440
  const moveThick = (t) => {
9278
- const tc = _optionalChain([t, 'optionalAccess', _587 => _587[layer.id]]);
9441
+ const tc = _optionalChain([t, 'optionalAccess', _596 => _596[layer.id]]);
9279
9442
  if (!tc) return t;
9280
9443
  return { ...t, [layer.id]: { height: _chunk474IQG74cjs.translateSurface.call(void 0, tc.height, ox, oy), material: _chunk474IQG74cjs.translateSurface.call(void 0, tc.material, ox, oy), film: _chunk474IQG74cjs.translateSurface.call(void 0, tc.film, ox, oy) } };
9281
9444
  };
9282
- this.doc = { ...this.doc, layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => moved), ..._optionalChain([this, 'access', _588 => _588.doc, 'access', _589 => _589.thick, 'optionalAccess', _590 => _590[layer.id]]) ? { thick: moveThick(this.doc.thick) } : {} };
9283
- if (doc !== this.doc) doc = { ...doc, layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, doc.layers, layer.id, () => moved), ..._optionalChain([doc, 'access', _591 => _591.thick, 'optionalAccess', _592 => _592[layer.id]]) ? { thick: moveThick(doc.thick) } : {} };
9445
+ this.doc = { ...this.doc, layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => moved), ..._optionalChain([this, 'access', _597 => _597.doc, 'access', _598 => _598.thick, 'optionalAccess', _599 => _599[layer.id]]) ? { thick: moveThick(this.doc.thick) } : {} };
9446
+ if (doc !== this.doc) doc = { ...doc, layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, doc.layers, layer.id, () => moved), ..._optionalChain([doc, 'access', _600 => _600.thick, 'optionalAccess', _601 => _601[layer.id]]) ? { thick: moveThick(doc.thick) } : {} };
9284
9447
  layer = moved;
9285
9448
  }
9286
9449
  if (!this.wet.wetLayerIds().includes(layer.id) && this.wet.wetLayerIds().length >= _chunkMITQGHN3cjs.MAX_WET_LANES) {
@@ -9296,8 +9459,8 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9296
9459
  const seedW = _nullishCoalesce(init.seed, () => ( _chunk3K6HWEXZcjs.mix32.call(void 0, this.seedCounter * 2654435761 >>> 0) & 2147483647));
9297
9460
  const copiesW = (_nullishCoalesce(init.copies, () => ( this.strokeCopies()))).filter((m) => m.some((v, i) => v !== IDENTITY_AFFINE[i]));
9298
9461
  const wetMask = init.maskStencils ? this.stencilSelection(init.maskStencils) : init.stencils !== false ? this.stencilSelection() : null;
9299
- const needWetFilm = Boolean(brush.wet.tool === "paint" && brush.iridescence || brush.wet.tool === "blot" && _optionalChain([doc, 'access', _593 => _593.thick, 'optionalAccess', _594 => _594[id], 'optionalAccess', _595 => _595.film, 'access', _596 => _596.tiles, 'access', _597 => _597.size]));
9300
- const wetFilm = needWetFilm ? new FilmBuffer((_nullishCoalesce(_optionalChain([doc, 'access', _598 => _598.thick, 'optionalAccess', _599 => _599[id]]), () => ( emptyThickChannels()))).film, layer.offset, wetMask) : null;
9462
+ const needWetFilm = Boolean(brush.wet.tool === "paint" && brush.iridescence || brush.wet.tool === "blot" && _optionalChain([doc, 'access', _602 => _602.thick, 'optionalAccess', _603 => _603[id], 'optionalAccess', _604 => _604.film, 'access', _605 => _605.tiles, 'access', _606 => _606.size]));
9463
+ const wetFilm = needWetFilm ? new FilmBuffer((_nullishCoalesce(_optionalChain([doc, 'access', _607 => _607.thick, 'optionalAccess', _608 => _608[id]]), () => ( emptyThickChannels()))).film, layer.offset, wetMask) : null;
9301
9464
  const driver = new (0, _chunkPEQWARCPcjs.WetStrokeDriver)({
9302
9465
  world,
9303
9466
  laneId: id,
@@ -9311,7 +9474,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9311
9474
  copies: [IDENTITY_AFFINE, ...copiesW].map(affineCopy),
9312
9475
  mask: wetMask,
9313
9476
  paint: effect ? null : wetGradient,
9314
- effect: _nullishCoalesce(_optionalChain([effect, 'optionalAccess', _600 => _600.pixels]), () => ( null)),
9477
+ effect: _nullishCoalesce(_optionalChain([effect, 'optionalAccess', _609 => _609.pixels]), () => ( null)),
9315
9478
  film: wetFilm,
9316
9479
  speed: this.wet.speed
9317
9480
  });
@@ -9325,7 +9488,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9325
9488
  if (brush.mutation && !_chunkHRUK5TFWcjs.isWetBrush.call(void 0, brush) && !this.answeringMutation && !this.previewing && !this.getOrigin().startsWith("agent:")) {
9326
9489
  const targetLayer = layer;
9327
9490
  const existing = this.mutations.find((m) => m.state === "settling" && m.medium === "dry" && m.layerId === targetLayer.id && m.tempLayerId && _chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, m.tempLayerId));
9328
- if (_optionalChain([existing, 'optionalAccess', _601 => _601.tempLayerId])) {
9491
+ if (_optionalChain([existing, 'optionalAccess', _610 => _610.tempLayerId])) {
9329
9492
  layer = _chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, existing.tempLayerId).layer;
9330
9493
  } else {
9331
9494
  const temp = {
@@ -9341,7 +9504,12 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9341
9504
  }
9342
9505
  let color = init.color === void 0 ? _nullishCoalesce(this.ownColour(init.brushId), () => ( this.color)) : parseColor(init.color);
9343
9506
  const tracing = this.guides.tracing;
9344
- if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _602 => _602.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
9507
+ const traced = init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _611 => _611.visible]) && tracing.sampleColors ? this.sampleTracingColor(init.start.x, init.start.y) : null;
9508
+ if (traced) color = traced;
9509
+ else if (init.color === void 0) {
9510
+ dualColor = this.dualPaint(init.brushId);
9511
+ if (dualColor) color = dualColor[scheme];
9512
+ }
9345
9513
  const perspective = this.guides.perspective;
9346
9514
  const snapper = init.snapToPerspective && perspective.enabled && perspective.snap ? new PerspectiveSnapper(perspective) : null;
9347
9515
  const useStencils = init.stencils !== false;
@@ -9355,8 +9523,9 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9355
9523
  const rgba = rgbaOf(color);
9356
9524
  const seed = _nullishCoalesce(init.seed, () => ( _chunk3K6HWEXZcjs.mix32.call(void 0, this.seedCounter++ * 2654435761 >>> 0) & 2147483647));
9357
9525
  const copies = (_nullishCoalesce(init.copies, () => ( this.strokeCopies()))).filter((m) => m.some((v, i) => v !== IDENTITY_AFFINE[i]));
9358
- const hasThick = Boolean(_optionalChain([doc, 'access', _603 => _603.thick, 'optionalAccess', _604 => _604[layer.id]]));
9359
- const needThick = brush.engine === "impasto" || Boolean(brush.iridescence) || brush.engine === "eraser" && hasThick || Boolean(_optionalChain([wet, 'optionalAccess', _605 => _605.driver, 'access', _606 => _606.init, 'access', _607 => _607.film]));
9526
+ const hasThick = Boolean(_optionalChain([doc, 'access', _612 => _612.thick, 'optionalAccess', _613 => _613[layer.id]]));
9527
+ const needThick = brush.engine === "impasto" || Boolean(brush.iridescence) || brush.engine === "eraser" && hasThick || Boolean(_optionalChain([wet, 'optionalAccess', _614 => _614.driver, 'access', _615 => _615.init, 'access', _616 => _616.film]));
9528
+ const gradient = effect ? null : this.strokeGradient(init, brush, color);
9360
9529
  const session = new PaintStrokeSession(host, {
9361
9530
  layerId: layer.id,
9362
9531
  surface: layer.surface,
@@ -9369,6 +9538,8 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9369
9538
  paperDepth: doc.paper.depth,
9370
9539
  seed,
9371
9540
  colorHex: color,
9541
+ // Only a stroke that paints its one colour keeps the pair (gradient and effect paint have their own colours).
9542
+ ...dualColor && !gradient && !effect && dualColor[scheme] === color ? { dualColor } : {},
9372
9543
  affineCopies: copies,
9373
9544
  copies: [IDENTITY_AFFINE, ...copies].map(affineCopy),
9374
9545
  inputFilter,
@@ -9376,16 +9547,16 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9376
9547
  mixerLoad: _nullishCoalesce(init.load, () => ( brushLoadForStroke(brush, this.mixerLoad, [rgba[0] / 255, rgba[1] / 255, rgba[2] / 255]))),
9377
9548
  secondary: rgbaOf(this.secondaryColor),
9378
9549
  wet,
9379
- thick: needThick ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _608 => _608.thick, 'optionalAccess', _609 => _609[layer.id]]), () => ( emptyThickChannels())) } : void 0,
9550
+ thick: needThick ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _617 => _617.thick, 'optionalAccess', _618 => _618[layer.id]]), () => ( emptyThickChannels())) } : void 0,
9380
9551
  // Light paint: a twin of the stroke paints the light channel (laying, dimming, moving light).
9381
- light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || _optionalChain([doc, 'access', _610 => _610.light, 'optionalAccess', _611 => _611[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _612 => _612.light, 'optionalAccess', _613 => _613[layer.id]]), () => ( emptyLight())) } : null,
9552
+ light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || _optionalChain([doc, 'access', _619 => _619.light, 'optionalAccess', _620 => _620[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _621 => _621.light, 'optionalAccess', _622 => _622[layer.id]]), () => ( emptyLight())) } : null,
9382
9553
  // Ferrofluid paint: a twin of the stroke paints the liquid ferrofluid channel.
9383
- ferro: !wet && brush.engine !== "sticker" && (brush.ferro.amount > 0 || _optionalChain([doc, 'access', _614 => _614.ferro, 'optionalAccess', _615 => _615[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _616 => _616.ferro, 'optionalAccess', _617 => _617[layer.id]]), () => ( emptyFerro())) } : null,
9384
- fluor: brush.engine !== "sticker" && (brush.fluorescence.amount > 0 || _optionalChain([doc, 'access', _618 => _618.fluor, 'optionalAccess', _619 => _619[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _620 => _620.fluor, 'optionalAccess', _621 => _621[layer.id]]), () => ( emptyFluor())) } : null,
9385
- thermo: brush.engine !== "sticker" && (brush.thermochromic.hotColor !== null || _optionalChain([doc, 'access', _622 => _622.thermo, 'optionalAccess', _623 => _623[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _624 => _624.thermo, 'optionalAccess', _625 => _625[layer.id]]), () => ( emptyThermo())) } : null,
9554
+ ferro: !wet && brush.engine !== "sticker" && (brush.ferro.amount > 0 || _optionalChain([doc, 'access', _623 => _623.ferro, 'optionalAccess', _624 => _624[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _625 => _625.ferro, 'optionalAccess', _626 => _626[layer.id]]), () => ( emptyFerro())) } : null,
9555
+ fluor: brush.engine !== "sticker" && (brush.fluorescence.amount > 0 || _optionalChain([doc, 'access', _627 => _627.fluor, 'optionalAccess', _628 => _628[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _629 => _629.fluor, 'optionalAccess', _630 => _630[layer.id]]), () => ( emptyFluor())) } : null,
9556
+ thermo: brush.engine !== "sticker" && (brush.thermochromic.hotColor !== null || _optionalChain([doc, 'access', _631 => _631.thermo, 'optionalAccess', _632 => _632[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _633 => _633.thermo, 'optionalAccess', _634 => _634[layer.id]]), () => ( emptyThermo())) } : null,
9386
9557
  sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc), art: this.stickerArt.get, variant: (ref2) => this.stickerArt.variantFor(ref2, this.colorScheme === "dark") } : void 0,
9387
9558
  stampArt: this.stampArt,
9388
- paint: effect ? null : this.strokeGradient(init, brush, color),
9559
+ paint: gradient,
9389
9560
  effect
9390
9561
  });
9391
9562
  if (wet) this.wet.driver = wet.driver;
@@ -9402,6 +9573,10 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9402
9573
  points: session.points.map((p) => ({ ...p })),
9403
9574
  seed: init.seed
9404
9575
  };
9576
+ if (init.dualColor) {
9577
+ stroke.dualColor = { ...init.dualColor };
9578
+ if (_optionalChain([this, 'access', _635 => _635.doc, 'access', _636 => _636.liveStrokes, 'optionalAccess', _637 => _637[session.layerId]])) stroke.color = init.dualColor.light;
9579
+ }
9405
9580
  if (init.affineCopies.length) stroke.copies = init.affineCopies.map((m) => [...m]);
9406
9581
  if (init.effect) stroke.paint = JSON.parse(JSON.stringify(init.effect.source));
9407
9582
  else if (init.paint) stroke.paint = JSON.parse(JSON.stringify(init.paint));
@@ -9422,21 +9597,21 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9422
9597
  const before = this.doc;
9423
9598
  const host = {
9424
9599
  update: (layerId, surface, rects) => {
9425
- if (_optionalChain([this, 'access', _626 => _626.session, 'optionalAccess', _627 => _627.init, 'access', _628 => _628.wet])) {
9600
+ if (_optionalChain([this, 'access', _638 => _638.session, 'optionalAccess', _639 => _639.init, 'access', _640 => _640.wet])) {
9426
9601
  const ch2 = this.session.thickChannels();
9427
9602
  this.liveThick = ch2 ? { layerId, channels: ch2 } : null;
9428
9603
  this.wet.syncDisplays();
9429
9604
  return;
9430
9605
  }
9431
9606
  this.live = { layerId, surface };
9432
- const ch = _optionalChain([this, 'access', _629 => _629.session, 'optionalAccess', _630 => _630.thickChannels, 'call', _631 => _631()]);
9607
+ const ch = _optionalChain([this, 'access', _641 => _641.session, 'optionalAccess', _642 => _642.thickChannels, 'call', _643 => _643()]);
9433
9608
  this.liveThick = ch ? { layerId, channels: ch } : null;
9434
- const fc = _optionalChain([this, 'access', _632 => _632.session, 'optionalAccess', _633 => _633.ferroChannel, 'call', _634 => _634()]);
9435
- const fb = _optionalChain([this, 'access', _635 => _635.session, 'optionalAccess', _636 => _636.init, 'access', _637 => _637.brush, 'access', _638 => _638.ferro]);
9436
- this.liveFerro = fc ? { layerId, surface: fc, settings: fb && fb.amount > 0 ? fb : _nullishCoalesce(_optionalChain([this, 'access', _639 => _639.doc, 'access', _640 => _640.ferroSettings, 'optionalAccess', _641 => _641[layerId]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO)) } : null;
9437
- const fl = _optionalChain([this, 'access', _642 => _642.session, 'optionalAccess', _643 => _643.fluorChannel, 'call', _644 => _644()]);
9609
+ const fc = _optionalChain([this, 'access', _644 => _644.session, 'optionalAccess', _645 => _645.ferroChannel, 'call', _646 => _646()]);
9610
+ const fb = _optionalChain([this, 'access', _647 => _647.session, 'optionalAccess', _648 => _648.init, 'access', _649 => _649.brush, 'access', _650 => _650.ferro]);
9611
+ this.liveFerro = fc ? { layerId, surface: fc, settings: fb && fb.amount > 0 ? fb : _nullishCoalesce(_optionalChain([this, 'access', _651 => _651.doc, 'access', _652 => _652.ferroSettings, 'optionalAccess', _653 => _653[layerId]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO)) } : null;
9612
+ const fl = _optionalChain([this, 'access', _654 => _654.session, 'optionalAccess', _655 => _655.fluorChannel, 'call', _656 => _656()]);
9438
9613
  this.liveFluor = fl ? { layerId, surface: fl } : null;
9439
- const th = _optionalChain([this, 'access', _645 => _645.session, 'optionalAccess', _646 => _646.thermoChannel, 'call', _647 => _647()]);
9614
+ const th = _optionalChain([this, 'access', _657 => _657.session, 'optionalAccess', _658 => _658.thermoChannel, 'call', _659 => _659()]);
9440
9615
  this.liveThermo = th ? { layerId, surface: th } : null;
9441
9616
  this.emit(rects);
9442
9617
  },
@@ -9446,7 +9621,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9446
9621
  },
9447
9622
  commit: (s, surface, cancelled) => {
9448
9623
  this.session = null;
9449
- const preview = _optionalChain([this, 'access', _648 => _648.pathPreview, 'optionalAccess', _649 => _649.session]) === s ? this.pathPreview : null;
9624
+ const preview = _optionalChain([this, 'access', _660 => _660.pathPreview, 'optionalAccess', _661 => _661.session]) === s ? this.pathPreview : null;
9450
9625
  this.pathPreview = null;
9451
9626
  const pathPaint = cancelled ? null : this.pathStrokePaint(s);
9452
9627
  if (pathPaint) {
@@ -9462,7 +9637,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9462
9637
  const wetStroke = Boolean(s.init.wet);
9463
9638
  if (wetStroke) this.wet.driver = null;
9464
9639
  const brush = s.init.brush;
9465
- if (!cancelled && _optionalChain([s, 'access', _650 => _650.result, 'optionalAccess', _651 => _651.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
9640
+ if (!cancelled && _optionalChain([s, 'access', _662 => _662.result, 'optionalAccess', _663 => _663.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
9466
9641
  if (cancelled || !surface) {
9467
9642
  if (this.wetOp) {
9468
9643
  const snap = this.wetOp.before;
@@ -9480,7 +9655,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9480
9655
  }
9481
9656
  const stroke = this.record(s);
9482
9657
  s.result.strokeId = stroke.id;
9483
- this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _652 => _652.result, 'optionalAccess', _653 => _653.bounds]), () => ( null)));
9658
+ this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _664 => _664.result, 'optionalAccess', _665 => _665.bounds]), () => ( null)));
9484
9659
  if (wetStroke && this.wet.instantDry) {
9485
9660
  this.wet.dry(s.layerId);
9486
9661
  this.logWet({ kind: "dry", layerId: s.layerId, at: this.doc.strokes.length + 1 });
@@ -9491,10 +9666,10 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9491
9666
  let ch = s.thickChannels();
9492
9667
  if (wetStroke) {
9493
9668
  const f = this.wet.patterns.get(l.id);
9494
- if (_optionalChain([f, 'optionalAccess', _654 => _654.enabled])) {
9669
+ if (_optionalChain([f, 'optionalAccess', _666 => _666.enabled])) {
9495
9670
  this.wet.settingsOf(l.id).livePatterns = { ...f.settings };
9496
9671
  if (f.settings.relief > 0 && f.tiles.size > 0) {
9497
- const prevCh = _nullishCoalesce(_nullishCoalesce(ch, () => ( _optionalChain([this, 'access', _655 => _655.doc, 'access', _656 => _656.thick, 'optionalAccess', _657 => _657[l.id]]))), () => ( emptyThickChannels()));
9672
+ const prevCh = _nullishCoalesce(_nullishCoalesce(ch, () => ( _optionalChain([this, 'access', _667 => _667.doc, 'access', _668 => _668.thick, 'optionalAccess', _669 => _669[l.id]]))), () => ( emptyThickChannels()));
9498
9673
  const nextHeight = f.applyReliefHeight(prevCh.height);
9499
9674
  if (nextHeight !== prevCh.height) ch = { ...prevCh, height: nextHeight };
9500
9675
  }
@@ -9502,48 +9677,57 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9502
9677
  }
9503
9678
  const thick = withLayerThick(this.doc.thick, l.id, ch);
9504
9679
  const sprayed = s.stickers();
9505
- const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _658 => _658.doc, 'access', _659 => _659.stickers, 'optionalAccess', _660 => _660[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
9506
- const wetLight = wetStroke && _optionalChain([this, 'access', _661 => _661.wet, 'access', _662 => _662.world, 'optionalAccess', _663 => _663.hasLane, 'call', _664 => _664(l.id)]) ? this.wet.world.lightDisplay(l.id) : null;
9680
+ const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _670 => _670.doc, 'access', _671 => _671.stickers, 'optionalAccess', _672 => _672[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
9681
+ const wetLight = wetStroke && _optionalChain([this, 'access', _673 => _673.wet, 'access', _674 => _674.world, 'optionalAccess', _675 => _675.hasLane, 'call', _676 => _676(l.id)]) ? this.wet.world.lightDisplay(l.id) : null;
9507
9682
  const light = withLayerLight(this.doc.light, l.id, _nullishCoalesce(s.lightChannel(), () => ( wetLight)));
9508
9683
  const fc = s.ferroChannel();
9509
9684
  const ferro = fc ? withLayerFerro(this.doc.ferro, l.id, fc) : this.doc.ferro;
9510
- const ferroSettings = fc ? withLayerFerroSettings(this.doc.ferroSettings, ferro, l.id, brush.ferro.amount > 0 ? brush.ferro : _nullishCoalesce(_optionalChain([this, 'access', _665 => _665.doc, 'access', _666 => _666.ferroSettings, 'optionalAccess', _667 => _667[l.id]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO))) : this.doc.ferroSettings;
9685
+ const ferroSettings = fc ? withLayerFerroSettings(this.doc.ferroSettings, ferro, l.id, brush.ferro.amount > 0 ? brush.ferro : _nullishCoalesce(_optionalChain([this, 'access', _677 => _677.doc, 'access', _678 => _678.ferroSettings, 'optionalAccess', _679 => _679[l.id]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO))) : this.doc.ferroSettings;
9511
9686
  const fluor = withLayerLight(this.doc.fluor, l.id, s.fluorChannel());
9512
9687
  const thermo = withLayerLight(this.doc.thermo, l.id, s.thermoChannel());
9513
- this.commit(
9514
- `${brush.name} stroke`,
9515
- this.withWetEvents(
9516
- withLiveStroke(
9517
- {
9518
- ...this.doc,
9519
- layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })),
9520
- strokes: [...this.doc.strokes, stroke],
9521
- ...thick ? { thick } : {},
9522
- ...stickers ? { stickers } : {},
9523
- ...light ? { light } : {},
9524
- ...fluor ? { fluor } : {},
9525
- ...thermo ? { thermo } : {},
9526
- ...ferro ? { ferro } : { ferro: void 0 },
9527
- ...ferroSettings ? { ferroSettings } : { ferroSettings: void 0 }
9528
- },
9529
- stroke
9530
- )
9531
- ),
9532
- before
9688
+ let next = this.withWetEvents(
9689
+ withLiveStroke(
9690
+ {
9691
+ ...this.doc,
9692
+ layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })),
9693
+ strokes: [...this.doc.strokes, stroke],
9694
+ ...thick ? { thick } : {},
9695
+ ...stickers ? { stickers } : {},
9696
+ ...light ? { light } : {},
9697
+ ...fluor ? { fluor } : {},
9698
+ ...thermo ? { thermo } : {},
9699
+ ...ferro ? { ferro } : { ferro: void 0 },
9700
+ ...ferroSettings ? { ferroSettings } : { ferroSettings: void 0 }
9701
+ },
9702
+ stroke
9703
+ )
9533
9704
  );
9534
- this.recordMutationStroke(stroke, _nullishCoalesce(_optionalChain([s, 'access', _668 => _668.result, 'optionalAccess', _669 => _669.bounds]), () => ( null)));
9705
+ const list = _optionalChain([next, 'access', _680 => _680.liveStrokes, 'optionalAccess', _681 => _681[l.id]]);
9706
+ if (list && (viewBase || stroke.color !== s.init.colorHex)) {
9707
+ const canonical = this.withLiveStrokes({ ...next, layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, next.layers, l.id, () => l) }, l, list, _optionalChain([s, 'access', _682 => _682.result, 'optionalAccess', _683 => _683.bounds]) ? [s.result.bounds] : null, { record: false });
9708
+ const drawn = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, canonical.layers, l.id), 'optionalAccess', _684 => _684.layer]);
9709
+ this.schemeViews.set(l.id, { scheme: viewScheme, list, base: drawn.surface, surface });
9710
+ next = canonical;
9711
+ }
9712
+ this.commit(`${brush.name} stroke`, next, before);
9713
+ this.recordMutationStroke(stroke, _nullishCoalesce(_optionalChain([s, 'access', _685 => _685.result, 'optionalAccess', _686 => _686.bounds]), () => ( null)));
9535
9714
  this.notifySample("end", s, [], stroke.id);
9536
9715
  }
9537
9716
  };
9717
+ const targetId = _nullishCoalesce(init.layerId, () => ( this.doc.activeLayerId));
9718
+ const target = targetId ? _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, targetId), 'optionalAccess', _687 => _687.layer]) : void 0;
9719
+ const targetStrokes = isPixelLayer(target) ? _optionalChain([this, 'access', _688 => _688.doc, 'access', _689 => _689.liveStrokes, 'optionalAccess', _690 => _690[target.id]]) : void 0;
9720
+ const viewBase = targetStrokes && isPixelLayer(target) ? this.schemeSurface(target, targetStrokes) : null;
9721
+ const viewScheme = this.colorScheme;
9538
9722
  let session;
9539
9723
  try {
9540
- session = this.sessionFor(this.doc, { snapToPerspective: true, ...init }, host);
9724
+ session = this.sessionFor(viewBase && target ? { ...this.doc, layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, this.doc.layers, target.id, (x) => ({ ...x, surface: viewBase })) } : this.doc, { snapToPerspective: true, ...init }, host);
9541
9725
  } catch (e) {
9542
9726
  this.wetOp = null;
9543
9727
  throw e;
9544
9728
  }
9545
9729
  this.session = session;
9546
- if (_optionalChain([session, 'access', _670 => _670.init, 'access', _671 => _671.effect, 'optionalAccess', _672 => _672.source, 'access', _673 => _673.map, 'optionalAccess', _674 => _674.by]) === "path" && !session.init.wet) this.pathPreview = { session, key: "", pending: null, landed: null };
9730
+ if (_optionalChain([session, 'access', _691 => _691.init, 'access', _692 => _692.effect, 'optionalAccess', _693 => _693.source, 'access', _694 => _694.map, 'optionalAccess', _695 => _695.by]) === "path" && !session.init.wet) this.pathPreview = { session, key: "", pending: null, landed: null };
9547
9731
  this.emit([]);
9548
9732
  this.notifySample("begin", session);
9549
9733
  return session;
@@ -9588,12 +9772,12 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9588
9772
  * the editor is busy, as during a stroke, and shows the stroke as it was painted.
9589
9773
  */
9590
9774
  get strokeRendering() {
9591
- return _nullishCoalesce(_optionalChain([this, 'access', _675 => _675.pathStroke, 'optionalAccess', _676 => _676.done]), () => ( null));
9775
+ return _nullishCoalesce(_optionalChain([this, 'access', _696 => _696.pathStroke, 'optionalAccess', _697 => _697.done]), () => ( null));
9592
9776
  }
9593
9777
  /** The paint a finished hand-painted stroke must be painted again with, or `null` when it already painted with it. */
9594
9778
  pathStrokePaint(s) {
9595
- const source = _optionalChain([s, 'access', _677 => _677.init, 'access', _678 => _678.effect, 'optionalAccess', _679 => _679.source]);
9596
- if (_optionalChain([source, 'optionalAccess', _680 => _680.map, 'optionalAccess', _681 => _681.by]) !== "path" || !s.points.length) return null;
9779
+ const source = _optionalChain([s, 'access', _698 => _698.init, 'access', _699 => _699.effect, 'optionalAccess', _700 => _700.source]);
9780
+ if (_optionalChain([source, 'optionalAccess', _701 => _701.map, 'optionalAccess', _702 => _702.by]) !== "path" || !s.points.length) return null;
9597
9781
  const paint = _chunkPEQWARCPcjs.withStrokePath.call(void 0, source, s.points, this.effectPathControls.get(source.effect));
9598
9782
  return _chunkPEQWARCPcjs.effectPaintKey.call(void 0, paint) === _chunkPEQWARCPcjs.effectPaintKey.call(void 0, source) ? null : paint;
9599
9783
  }
@@ -9614,17 +9798,17 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9614
9798
  this.liveThermo = null;
9615
9799
  const masks = s.init.selection ? (_nullishCoalesce(s.maskStencils, () => ( this.guides.stencils))).filter((x) => x.enabled && x.mode === "mask") : [];
9616
9800
  const load = s.init.mixerLoad;
9617
- const result = this.paintStroke({ layerId: s.layerId, points: s.points, color: s.init.colorHex, brush: _chunkHRUK5TFWcjs.brushToJSON.call(void 0, s.init.brush), seed: s.init.seed, copies: s.init.affineCopies, ...load.reservoir || load.pickup ? { load } : {}, paint, snapToPerspective: false, stencils: false, maskStencils: masks });
9801
+ const result = this.paintStroke({ layerId: s.layerId, points: s.points, color: _nullishCoalesce(s.init.dualColor, () => ( s.init.colorHex)), brush: _chunkHRUK5TFWcjs.brushToJSON.call(void 0, s.init.brush), seed: s.init.seed, copies: s.init.affineCopies, ...load.reservoir || load.pickup ? { load } : {}, paint, snapToPerspective: false, stencils: false, maskStencils: masks });
9618
9802
  Object.assign(s.result, result);
9619
9803
  this.notifySample("end", s, [], result.strokeId);
9620
9804
  };
9621
9805
  const key = _chunkPEQWARCPcjs.effectPaintKey.call(void 0, paint);
9622
- if (_optionalChain([preview, 'optionalAccess', _682 => _682.landed, 'optionalAccess', _683 => _683.key]) === key) this.cacheEffectPaintImage(paint, preview.landed.pixels);
9806
+ if (_optionalChain([preview, 'optionalAccess', _703 => _703.landed, 'optionalAccess', _704 => _704.key]) === key) this.cacheEffectPaintImage(paint, preview.landed.pixels);
9623
9807
  if (this.effectPaintImage(paint) || this.renderEffectPaintSync(paint)) {
9624
9808
  finish();
9625
9809
  return;
9626
9810
  }
9627
- const render = _optionalChain([preview, 'optionalAccess', _684 => _684.pending]) && preview.key === key ? preview.pending.then((img) => this.cacheEffectPaintImage(paint, img)) : this.renderEffectPaint(paint);
9811
+ const render = _optionalChain([preview, 'optionalAccess', _705 => _705.pending]) && preview.key === key ? preview.pending.then((img) => this.cacheEffectPaintImage(paint, img)) : this.renderEffectPaint(paint);
9628
9812
  const done = render.then(finish, (e) => {
9629
9813
  this.pathStroke = null;
9630
9814
  this.live = null;
@@ -9652,10 +9836,10 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9652
9836
  if (cancelled || !surface) return;
9653
9837
  const stroke = this.record(s);
9654
9838
  s.result.strokeId = stroke.id;
9655
- this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _685 => _685.result, 'optionalAccess', _686 => _686.bounds]), () => ( null)));
9839
+ this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _706 => _706.result, 'optionalAccess', _707 => _707.bounds]), () => ( null)));
9656
9840
  const targetId = this.tempLayerTargets.get(s.layerId);
9657
9841
  if (targetId && !_chunkPVJMTLPJcjs.findLayer.call(void 0, out.layers, s.layerId)) {
9658
- const temp = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, s.layerId), 'optionalAccess', _687 => _687.layer]);
9842
+ const temp = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, s.layerId), 'optionalAccess', _708 => _708.layer]);
9659
9843
  if (temp) out = { ...out, layers: insertAfter(out.layers, targetId, temp) };
9660
9844
  }
9661
9845
  const l = _chunkPVJMTLPJcjs.findLayer.call(void 0, out.layers, s.layerId).layer;
@@ -9663,10 +9847,10 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9663
9847
  let ch = s.thickChannels();
9664
9848
  if (s.init.wet) {
9665
9849
  const f = this.wet.patterns.get(l.id);
9666
- if (_optionalChain([f, 'optionalAccess', _688 => _688.enabled])) {
9850
+ if (_optionalChain([f, 'optionalAccess', _709 => _709.enabled])) {
9667
9851
  this.wet.settingsOf(l.id).livePatterns = { ...f.settings };
9668
9852
  if (f.settings.relief > 0 && f.tiles.size > 0) {
9669
- const prevCh = _nullishCoalesce(_nullishCoalesce(ch, () => ( _optionalChain([out, 'access', _689 => _689.thick, 'optionalAccess', _690 => _690[l.id]]))), () => ( emptyThickChannels()));
9853
+ const prevCh = _nullishCoalesce(_nullishCoalesce(ch, () => ( _optionalChain([out, 'access', _710 => _710.thick, 'optionalAccess', _711 => _711[l.id]]))), () => ( emptyThickChannels()));
9670
9854
  const nextHeight = f.applyReliefHeight(prevCh.height);
9671
9855
  if (nextHeight !== prevCh.height) ch = { ...prevCh, height: nextHeight };
9672
9856
  }
@@ -9674,14 +9858,14 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9674
9858
  }
9675
9859
  const thick = withLayerThick(out.thick, l.id, ch);
9676
9860
  const sprayed = s.stickers();
9677
- const lit = _nullishCoalesce(s.lightChannel(), () => ( (s.init.wet && _optionalChain([this, 'access', _691 => _691.wet, 'access', _692 => _692.world, 'optionalAccess', _693 => _693.hasLane, 'call', _694 => _694(l.id)]) ? this.wet.world.lightDisplay(l.id) : null)));
9861
+ const lit = _nullishCoalesce(s.lightChannel(), () => ( (s.init.wet && _optionalChain([this, 'access', _712 => _712.wet, 'access', _713 => _713.world, 'optionalAccess', _714 => _714.hasLane, 'call', _715 => _715(l.id)]) ? this.wet.world.lightDisplay(l.id) : null)));
9678
9862
  const fc = s.ferroChannel();
9679
9863
  const nextFerro = fc ? withLayerFerro(out.ferro, l.id, fc) : out.ferro;
9680
9864
  const nextFerroSettings = fc ? withLayerFerroSettings(
9681
9865
  out.ferroSettings,
9682
9866
  nextFerro,
9683
9867
  l.id,
9684
- s.init.brush.ferro.amount > 0 ? s.init.brush.ferro : _nullishCoalesce(_optionalChain([out, 'access', _695 => _695.ferroSettings, 'optionalAccess', _696 => _696[l.id]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO))
9868
+ s.init.brush.ferro.amount > 0 ? s.init.brush.ferro : _nullishCoalesce(_optionalChain([out, 'access', _716 => _716.ferroSettings, 'optionalAccess', _717 => _717[l.id]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO))
9685
9869
  ) : out.ferroSettings;
9686
9870
  const fl = s.fluorChannel();
9687
9871
  const th = s.thermoChannel();
@@ -9690,7 +9874,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9690
9874
  layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, out.layers, l.id, () => ({ ...l, surface, offset })),
9691
9875
  strokes: [...out.strokes, stroke],
9692
9876
  ...thick ? { thick } : {},
9693
- ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _697 => _697.stickers, 'optionalAccess', _698 => _698[l.id]]), () => ( [])), ...sprayed] } } : {},
9877
+ ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _718 => _718.stickers, 'optionalAccess', _719 => _719[l.id]]), () => ( [])), ...sprayed] } } : {},
9694
9878
  ...lit ? { light: withLayerLight(out.light, l.id, lit) } : {},
9695
9879
  ...fc ? { ferro: nextFerro, ferroSettings: nextFerroSettings } : {},
9696
9880
  ...fl ? { fluor: withLayerLight(out.fluor, l.id, fl) } : {},
@@ -9698,7 +9882,14 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9698
9882
  }, stroke);
9699
9883
  }
9700
9884
  };
9701
- const session = this.sessionFor(doc, init, host, points);
9885
+ const target = _nullishCoalesce(init.layerId, () => ( doc.activeLayerId));
9886
+ this.paintScheme = target && _optionalChain([doc, 'access', _720 => _720.liveStrokes, 'optionalAccess', _721 => _721[target]]) ? "light" : null;
9887
+ let session;
9888
+ try {
9889
+ session = this.sessionFor(doc, init, host, points);
9890
+ } finally {
9891
+ this.paintScheme = null;
9892
+ }
9702
9893
  session.push(points);
9703
9894
  const result = session.end();
9704
9895
  if (session.init.wet) {
@@ -9769,16 +9960,16 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9769
9960
  throw e;
9770
9961
  }
9771
9962
  const run = last;
9772
- if (_optionalChain([run, 'optionalAccess', _699 => _699.result, 'access', _700 => _700.mixerLoad])) this.keepLoad(run.brush, run.result.mixerLoad);
9963
+ if (_optionalChain([run, 'optionalAccess', _722 => _722.result, 'access', _723 => _723.mixerLoad])) this.keepLoad(run.brush, run.result.mixerLoad);
9773
9964
  if (doc !== before || this.wetOp) {
9774
- this.commit(`${_nullishCoalesce(_optionalChain([run, 'optionalAccess', _701 => _701.brush, 'access', _702 => _702.name]), () => ( "Brush"))} path stroke`, this.withWetEvents(doc), before);
9965
+ this.commit(`${_nullishCoalesce(_optionalChain([run, 'optionalAccess', _724 => _724.brush, 'access', _725 => _725.name]), () => ( "Brush"))} path stroke`, this.withWetEvents(doc), before);
9775
9966
  for (const sid of strokeIds) {
9776
9967
  const recorded = this.doc.strokes.find((s) => s.id === sid);
9777
9968
  if (recorded) this.recordMutationStroke(recorded, _nullishCoalesce(this.paintedBounds.get(recorded), () => ( null)));
9778
9969
  }
9779
9970
  } else this.emit([]);
9780
- const layerId = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([run, 'optionalAccess', _703 => _703.result, 'access', _704 => _704.layerId]), () => ( stroke.layerId)), () => ( this.doc.activeLayerId)), () => ( ""));
9781
- return { layerId, bounds, dabs, strokeIds, ..._optionalChain([run, 'optionalAccess', _705 => _705.result, 'access', _706 => _706.mixerLoad]) ? { mixerLoad: run.result.mixerLoad } : {}, ..._optionalChain([run, 'optionalAccess', _707 => _707.result, 'access', _708 => _708.wet]) !== void 0 ? { wet: run.result.wet } : {} };
9971
+ const layerId = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([run, 'optionalAccess', _726 => _726.result, 'access', _727 => _727.layerId]), () => ( stroke.layerId)), () => ( this.doc.activeLayerId)), () => ( ""));
9972
+ return { layerId, bounds, dabs, strokeIds, ..._optionalChain([run, 'optionalAccess', _728 => _728.result, 'access', _729 => _729.mixerLoad]) ? { mixerLoad: run.result.mixerLoad } : {}, ..._optionalChain([run, 'optionalAccess', _730 => _730.result, 'access', _731 => _731.wet]) !== void 0 ? { wet: run.result.wet } : {} };
9782
9973
  }
9783
9974
  /** Checks stroke samples (finite x and y, pressure 0..1) and returns them; throws a sentence naming the bad point. */
9784
9975
  checkPoints(points) {
@@ -9801,7 +9992,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9801
9992
  */
9802
9993
  replayStrokes(options) {
9803
9994
  this.requireIdle("replaying");
9804
- if (!_optionalChain([options, 'access', _709 => _709.strokeIds, 'optionalAccess', _710 => _710.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
9995
+ if (!_optionalChain([options, 'access', _732 => _732.strokeIds, 'optionalAccess', _733 => _733.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
9805
9996
  const strokes = options.strokeIds.map((id) => {
9806
9997
  const s = this.doc.strokes.find((x) => x.id === id);
9807
9998
  if (!s) throw new PaintEditorError(`Unknown stroke "${id}". Call list_strokes for the ids.`);
@@ -9815,7 +10006,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9815
10006
  if (options.layerId !== void 0) this.paintTarget(options.layerId, "replay onto");
9816
10007
  if (options.color === void 0) {
9817
10008
  for (const s of strokes) {
9818
- if (_optionalChain([s, 'access', _711 => _711.paint, 'optionalAccess', _712 => _712.type]) === "effect" && !this.effectPaintImage(s.paint)) {
10009
+ if (_optionalChain([s, 'access', _734 => _734.paint, 'optionalAccess', _735 => _735.type]) === "effect" && !this.effectPaintImage(s.paint)) {
9819
10010
  throw new PaintEditorError(`Stroke "${s.id}" paints with the effect "${s.paint.effect}"${s.paint.provider ? ` from provider "${s.paint.provider}"` : ""}, which is not rendered in this editor; render it first (prepareStrokeEffects; the replay_strokes tool does this) or recolour the replay with color.`);
9820
10011
  }
9821
10012
  }
@@ -9875,7 +10066,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9875
10066
  /** A layer's light paint: whether it has any, where (document pixels), its brightest value 0..255, and its spill. */
9876
10067
  lightOf(layerId) {
9877
10068
  const l = this.wetLayer(layerId, "read the light of");
9878
- const info = lightInfo(_optionalChain([this, 'access', _713 => _713.doc, 'access', _714 => _714.light, 'optionalAccess', _715 => _715[l.id]]));
10069
+ const info = lightInfo(_optionalChain([this, 'access', _736 => _736.doc, 'access', _737 => _737.light, 'optionalAccess', _738 => _738[l.id]]));
9879
10070
  const bounds = info.bounds ? { ...info.bounds, x: info.bounds.x + l.offset.x, y: info.bounds.y + l.offset.y } : null;
9880
10071
  return { layerId: l.id, hasLight: info.peak > 0, bounds, peak: info.peak, spill: { ...this.lightSpillOf(l.id) } };
9881
10072
  }
@@ -9992,7 +10183,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
9992
10183
  advanceHeat(stepsOrOptions = 10) {
9993
10184
  this.requireIdle("advancing heat");
9994
10185
  this.requireWetIdle("advancing heat");
9995
- const rawSteps = typeof stepsOrOptions === "number" ? stepsOrOptions : _optionalChain([stepsOrOptions, 'optionalAccess', _716 => _716.steps]);
10186
+ const rawSteps = typeof stepsOrOptions === "number" ? stepsOrOptions : _optionalChain([stepsOrOptions, 'optionalAccess', _739 => _739.steps]);
9996
10187
  const steps = _nullishCoalesce(rawSteps, () => ( 10));
9997
10188
  if (!(Number.isInteger(steps) && steps >= 1 && steps <= 200)) {
9998
10189
  throw new PaintEditorError(`steps ${rawSteps} is out of range; use a whole number 1..200.`);
@@ -10073,7 +10264,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10073
10264
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
10074
10265
  if (!id) return null;
10075
10266
  this.requireLayer(id);
10076
- const ch = _optionalChain([this, 'access', _717 => _717.doc, 'access', _718 => _718.thick, 'optionalAccess', _719 => _719[id]]);
10267
+ const ch = _optionalChain([this, 'access', _740 => _740.doc, 'access', _741 => _741.thick, 'optionalAccess', _742 => _742[id]]);
10077
10268
  if (!ch || !hasThickChannels(ch)) return null;
10078
10269
  const r = reliefInfo(ch);
10079
10270
  return { layerId: id, bounds: r.bounds, maxHeight: r.maxHeight };
@@ -10111,7 +10302,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10111
10302
  if (!f || !magnets.length) return f ? { ...f } : void 0;
10112
10303
  const out = {};
10113
10304
  for (const [id, surf] of Object.entries(f)) {
10114
- const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _720 => _720.layer]);
10305
+ const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _743 => _743.layer]);
10115
10306
  if (isPixelLayer(l) && surf.tiles.size > 0) {
10116
10307
  const next = advectFerro(surf, magnets, l.offset, steps);
10117
10308
  if (next.tiles.size > 0) out[id] = next;
@@ -10188,12 +10379,12 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10188
10379
  removeMagnets(ids) {
10189
10380
  this.requireIdle("removing magnets");
10190
10381
  const existing = _nullishCoalesce(this.doc.magnets, () => ( []));
10191
- if (_optionalChain([ids, 'optionalAccess', _721 => _721.length])) {
10382
+ if (_optionalChain([ids, 'optionalAccess', _744 => _744.length])) {
10192
10383
  for (const id of ids) {
10193
10384
  if (!existing.some((m) => m.id === id)) throw new PaintEditorError(`Unknown magnet "${id}". Call list_magnets for the ids.`);
10194
10385
  }
10195
10386
  }
10196
- const removed = _optionalChain([ids, 'optionalAccess', _722 => _722.length]) ? [...ids] : existing.map((m) => m.id);
10387
+ const removed = _optionalChain([ids, 'optionalAccess', _745 => _745.length]) ? [...ids] : existing.map((m) => m.id);
10197
10388
  if (!removed.length) return [];
10198
10389
  const next = existing.filter((m) => !removed.includes(m.id));
10199
10390
  const nextDoc = this.withPaintEvent(
@@ -10212,9 +10403,9 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10212
10403
  /** Reads a layer's liquid ferrofluid coverage and active Rosensweig spike relief under the canvas magnets. */
10213
10404
  getFerrofluid(layerId) {
10214
10405
  const l = this.wetLayer(layerId, "read the ferrofluid of");
10215
- const settings = _nullishCoalesce(_optionalChain([this, 'access', _723 => _723.doc, 'access', _724 => _724.ferroSettings, 'optionalAccess', _725 => _725[l.id]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO));
10406
+ const settings = _nullishCoalesce(_optionalChain([this, 'access', _746 => _746.doc, 'access', _747 => _747.ferroSettings, 'optionalAccess', _748 => _748[l.id]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO));
10216
10407
  const magnets = _nullishCoalesce(this.doc.magnets, () => ( []));
10217
- const info = ferroInfo(_optionalChain([this, 'access', _726 => _726.doc, 'access', _727 => _727.ferro, 'optionalAccess', _728 => _728[l.id]]), magnets, settings, l.offset);
10408
+ const info = ferroInfo(_optionalChain([this, 'access', _749 => _749.doc, 'access', _750 => _750.ferro, 'optionalAccess', _751 => _751[l.id]]), magnets, settings, l.offset);
10218
10409
  const bounds = info.bounds ? { ...info.bounds, x: info.bounds.x + l.offset.x, y: info.bounds.y + l.offset.y } : null;
10219
10410
  return {
10220
10411
  layerId: l.id,
@@ -10233,15 +10424,15 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10233
10424
  cureFerrofluid(layerId) {
10234
10425
  this.requireIdle("curing ferrofluid");
10235
10426
  const l = this.paintTarget(layerId, "cure the ferrofluid of");
10236
- const fSurf = _optionalChain([this, 'access', _729 => _729.doc, 'access', _730 => _730.ferro, 'optionalAccess', _731 => _731[l.id]]);
10427
+ const fSurf = _optionalChain([this, 'access', _752 => _752.doc, 'access', _753 => _753.ferro, 'optionalAccess', _754 => _754[l.id]]);
10237
10428
  if (!fSurf || !fSurf.tiles.size) {
10238
10429
  return { layerId: l.id, cured: false, bounds: null, maxSpikeHeight: 0, activeSpikeArea: 0 };
10239
10430
  }
10240
- const settings = _nullishCoalesce(_optionalChain([this, 'access', _732 => _732.doc, 'access', _733 => _733.ferroSettings, 'optionalAccess', _734 => _734[l.id]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO));
10431
+ const settings = _nullishCoalesce(_optionalChain([this, 'access', _755 => _755.doc, 'access', _756 => _756.ferroSettings, 'optionalAccess', _757 => _757[l.id]]), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO));
10241
10432
  const magnets = _nullishCoalesce(this.doc.magnets, () => ( []));
10242
10433
  const fb = ferroInfo(fSurf, magnets, settings, l.offset).bounds;
10243
10434
  const bounds = fb ? { ...fb, x: fb.x + l.offset.x, y: fb.y + l.offset.y } : null;
10244
- const baked = bakeFerroIntoThick(l.surface, fSurf, _optionalChain([this, 'access', _735 => _735.doc, 'access', _736 => _736.thick, 'optionalAccess', _737 => _737[l.id]]), magnets, settings, l.offset);
10435
+ const baked = bakeFerroIntoThick(l.surface, fSurf, _optionalChain([this, 'access', _758 => _758.doc, 'access', _759 => _759.thick, 'optionalAccess', _760 => _760[l.id]]), magnets, settings, l.offset);
10245
10436
  const removed = this.ferroWithout([l.id]);
10246
10437
  const nextDoc = {
10247
10438
  ...this.doc,
@@ -10358,7 +10549,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10358
10549
  wetState() {
10359
10550
  const st = this.getState().wet;
10360
10551
  const backend = this.wet.backend();
10361
- return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _738 => _738.message]), () => ( _chunkMITQGHN3cjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
10552
+ return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _761 => _761.message]), () => ( _chunkMITQGHN3cjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
10362
10553
  }
10363
10554
  /**
10364
10555
  * Engine B, the WebGPU accelerator for large wet areas: whether it may run, its state (`off`,
@@ -10449,7 +10640,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10449
10640
  }
10450
10641
  /** Records a settings change as a wet event (not an undo step). */
10451
10642
  recordWetSetting(e) {
10452
- this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _739 => _739.wet, 'access', _740 => _740.world, 'optionalAccess', _741 => _741.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
10643
+ this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _762 => _762.wet, 'access', _763 => _763.world, 'optionalAccess', _764 => _764.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
10453
10644
  }
10454
10645
  /** Changes a layer's wet settings (viscosity, evaporation, granulation…). Editor settings saved with the document, not an undo step. */
10455
10646
  setWetParams(layerId, update) {
@@ -10669,9 +10860,9 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10669
10860
  const override = this.frameOverride;
10670
10861
  if (override) return Array.from(override).reduce((ls, [id, surface]) => _chunkPVJMTLPJcjs.mapLayer.call(void 0, ls, id, (l) => ({ ...l, surface })), this.doc.layers);
10671
10862
  const live = this.live;
10672
- if (!live) return this.animatedView();
10673
- if (_optionalChain([this, 'access', _742 => _742.liveLayers, 'optionalAccess', _743 => _743.key]) === live.surface) return this.liveLayers.layers;
10674
- const layers = _chunkPVJMTLPJcjs.mapLayer.call(void 0, this.doc.layers, live.layerId, (l) => ({ ...l, surface: live.surface }));
10863
+ if (!live) return this.schemeLayers(this.animatedView());
10864
+ if (_optionalChain([this, 'access', _765 => _765.liveLayers, 'optionalAccess', _766 => _766.key]) === live.surface) return this.liveLayers.layers;
10865
+ const layers = _chunkPVJMTLPJcjs.mapLayer.call(void 0, this.schemeLayers(this.doc.layers), live.layerId, (l) => ({ ...l, surface: live.surface }));
10675
10866
  this.liveLayers = { key: live.surface, layers };
10676
10867
  return layers;
10677
10868
  }
@@ -10693,7 +10884,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10693
10884
  tracingNode(t) {
10694
10885
  const { width, height } = this.doc.canvas;
10695
10886
  const key = this.tracingVersion * 100003 + width * 7 + height;
10696
- if (_optionalChain([this, 'access', _744 => _744.tracingCache, 'optionalAccess', _745 => _745.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
10887
+ if (_optionalChain([this, 'access', _767 => _767.tracingCache, 'optionalAccess', _768 => _768.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
10697
10888
  const src = _nullishCoalesce(this.imagePixels.get(t.src), () => ( this.decodeImage(t.src)));
10698
10889
  const image = resampleInto(src, t.rect, width, height);
10699
10890
  const node = { type: "image", id: TRACING_NODE_ID, name: "Tracing", visible: true, opacity: t.opacity, blend: "normal", image, version: key + Math.round(t.opacity * 1e3) / 1e4 };
@@ -10719,7 +10910,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10719
10910
  if (!thermo || !heat || heat.max === 0) return layers;
10720
10911
  let out = layers;
10721
10912
  for (const [id, th] of Object.entries(thermo)) {
10722
- const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, out, id), 'optionalAccess', _746 => _746.layer]);
10913
+ const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, out, id), 'optionalAccess', _769 => _769.layer]);
10723
10914
  if (!isPixelLayer(l) || !th.tiles.size) continue;
10724
10915
  let cache = this.thermoCaches.get(id);
10725
10916
  if (!cache) this.thermoCaches.set(id, cache = new ThermoCache());
@@ -10777,11 +10968,11 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10777
10968
  ]);
10778
10969
  const magnets = _nullishCoalesce(this.doc.magnets, () => ( []));
10779
10970
  for (const id of ids) {
10780
- const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, out, id), 'optionalAccess', _747 => _747.layer]);
10971
+ const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, out, id), 'optionalAccess', _770 => _770.layer]);
10781
10972
  if (!isPixelLayer(l)) continue;
10782
- const ch = _nullishCoalesce((_optionalChain([live, 'optionalAccess', _748 => _748.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _749 => _749[id]])), () => ( emptyThickChannels()));
10783
- const fSurf = _optionalChain([liveFerro, 'optionalAccess', _750 => _750.layerId]) === id ? liveFerro.surface : _optionalChain([ferro, 'optionalAccess', _751 => _751[id]]);
10784
- const fSet = _nullishCoalesce((_optionalChain([liveFerro, 'optionalAccess', _752 => _752.layerId]) === id ? liveFerro.settings : _optionalChain([this, 'access', _753 => _753.doc, 'access', _754 => _754.ferroSettings, 'optionalAccess', _755 => _755[id]])), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO));
10973
+ const ch = _nullishCoalesce((_optionalChain([live, 'optionalAccess', _771 => _771.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _772 => _772[id]])), () => ( emptyThickChannels()));
10974
+ const fSurf = _optionalChain([liveFerro, 'optionalAccess', _773 => _773.layerId]) === id ? liveFerro.surface : _optionalChain([ferro, 'optionalAccess', _774 => _774[id]]);
10975
+ const fSet = _nullishCoalesce((_optionalChain([liveFerro, 'optionalAccess', _775 => _775.layerId]) === id ? liveFerro.settings : _optionalChain([this, 'access', _776 => _776.doc, 'access', _777 => _777.ferroSettings, 'optionalAccess', _778 => _778[id]])), () => ( _chunkHRUK5TFWcjs.DEFAULT_FERRO));
10785
10976
  const hasThick = ch.height.tiles.size > 0 || ch.material.tiles.size > 0 || ch.film.tiles.size > 0;
10786
10977
  const hasFerro = Boolean(fSurf && fSurf.tiles.size > 0);
10787
10978
  if (!hasThick && !hasFerro) continue;
@@ -10803,13 +10994,13 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10803
10994
  if (!ids.size) return layers;
10804
10995
  let out = layers;
10805
10996
  for (const id of ids) {
10806
- const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, out, id), 'optionalAccess', _756 => _756.layer]);
10997
+ const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, out, id), 'optionalAccess', _779 => _779.layer]);
10807
10998
  if (!isPixelLayer(l)) continue;
10808
10999
  let cache = this.lightCaches.get(id);
10809
11000
  if (!cache) this.lightCaches.set(id, cache = new LightCache());
10810
- const glowed = cache.glow(l.surface, light[id], _optionalChain([this, 'access', _757 => _757.liveThick, 'optionalAccess', _758 => _758.layerId]) === id ? this.liveThick.channels : _optionalChain([this, 'access', _759 => _759.doc, 'access', _760 => _760.thick, 'optionalAccess', _761 => _761[id]]));
11001
+ const glowed = cache.glow(l.surface, light[id], _optionalChain([this, 'access', _780 => _780.liveThick, 'optionalAccess', _781 => _781.layerId]) === id ? this.liveThick.channels : _optionalChain([this, 'access', _782 => _782.doc, 'access', _783 => _783.thick, 'optionalAccess', _784 => _784[id]]));
10811
11002
  if (glowed !== l.surface) out = _chunkPVJMTLPJcjs.mapLayer.call(void 0, out, id, () => ({ ...l, surface: glowed }));
10812
- const committed = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _762 => _762.layer]);
11003
+ const committed = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _785 => _785.layer]);
10813
11004
  const spill = light[id] && isPixelLayer(committed) ? cache.spill(committed.surface, light[id], this.lightSpillOf(id)) : null;
10814
11005
  if (spill) out = insertAfter(out, id, { type: "pixel", id: `${id}${SPILL_SUFFIX}`, name: `${l.name} light`, visible: l.visible, opacity: l.opacity, blend: "linear-dodge", surface: spill, offset: { ...l.offset } });
10815
11006
  }
@@ -10821,7 +11012,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10821
11012
  if (!l.visible) continue;
10822
11013
  if (l.type === "group") this.backlitLayers(l.children, committed, opacity * l.opacity, out);
10823
11014
  else if (isPixelLayer(l)) {
10824
- const thick = !committed && _optionalChain([this, 'access', _763 => _763.liveThick, 'optionalAccess', _764 => _764.layerId]) === l.id ? this.liveThick.channels : _optionalChain([this, 'access', _765 => _765.doc, 'access', _766 => _766.thick, 'optionalAccess', _767 => _767[l.id]]);
11015
+ const thick = !committed && _optionalChain([this, 'access', _786 => _786.liveThick, 'optionalAccess', _787 => _787.layerId]) === l.id ? this.liveThick.channels : _optionalChain([this, 'access', _788 => _788.doc, 'access', _789 => _789.thick, 'optionalAccess', _790 => _790[l.id]]);
10825
11016
  out.push({ surface: l.surface, offset: l.offset, opacity: opacity * l.opacity, ...thick ? { thick } : {} });
10826
11017
  }
10827
11018
  }
@@ -10850,7 +11041,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10850
11041
  if (backlight) layers = [...layers, backlight];
10851
11042
  if (options.layerIds) {
10852
11043
  const picked = [];
10853
- for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _768 => _768.layer]), () => ( this.requireLayer(id))));
11044
+ for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _791 => _791.layer]), () => ( this.requireLayer(id))));
10854
11045
  layers = picked.map((l) => ({ ...l, visible: true }));
10855
11046
  }
10856
11047
  const under = options.paper === false ? [] : [paperNode(uvPaper(this.doc.paper, this.uvLight), this.lighting)];
@@ -10866,7 +11057,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10866
11057
  */
10867
11058
  compositeTiles(rect, onTile, options = {}) {
10868
11059
  const dirty = options.dirty === "all" ? void 0 : options.dirty;
10869
- this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _769 => _769.live, 'optionalAccess', _770 => _770.layerId]), () => ( this.doc.activeLayerId)) });
11060
+ this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _792 => _792.live, 'optionalAccess', _793 => _793.layerId]), () => ( this.doc.activeLayerId)) });
10870
11061
  }
10871
11062
  /** The canvas as canvas-sized RGBA (paper included by default). */
10872
11063
  compositePixels(options = {}) {
@@ -10924,8 +11115,8 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
10924
11115
  const layers = {};
10925
11116
  for (const [id, set] of this.wet.settings) {
10926
11117
  if (!_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, id)) continue;
10927
- const ghost = _optionalChain([this, 'access', _771 => _771.wet, 'access', _772 => _772.world, 'optionalAccess', _773 => _773.hasLane, 'call', _774 => _774(id)]) ? this.wet.world.getGhost(id) : _nullishCoalesce(set.ghost, () => ( null));
10928
- const savedGhost = _optionalChain([ghost, 'optionalAccess', _775 => _775.trigger]) === "agent" ? null : ghost;
11118
+ const ghost = _optionalChain([this, 'access', _794 => _794.wet, 'access', _795 => _795.world, 'optionalAccess', _796 => _796.hasLane, 'call', _797 => _797(id)]) ? this.wet.world.getGhost(id) : _nullishCoalesce(set.ghost, () => ( null));
11119
+ const savedGhost = _optionalChain([ghost, 'optionalAccess', _798 => _798.trigger]) === "agent" ? null : ghost;
10929
11120
  const heldEvap = this.heldEvaporation.get(id);
10930
11121
  const params = heldEvap !== void 0 ? { ...set.params, evaporation: heldEvap } : { ...set.params };
10931
11122
  layers[id] = {
@@ -11001,14 +11192,14 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11001
11192
  const ferro = {};
11002
11193
  for (const [id, f] of Object.entries(_nullishCoalesce(this.doc.ferro, () => ( {})))) {
11003
11194
  if (!_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, id)) continue;
11004
- const saved = ferroToJSON(f, _optionalChain([this, 'access', _776 => _776.doc, 'access', _777 => _777.ferroSettings, 'optionalAccess', _778 => _778[id]]));
11195
+ const saved = ferroToJSON(f, _optionalChain([this, 'access', _799 => _799.doc, 'access', _800 => _800.ferroSettings, 'optionalAccess', _801 => _801[id]]));
11005
11196
  if (saved) ferro[id] = saved;
11006
11197
  }
11007
11198
  if (Object.keys(ferro).length) ext.ferro = ferro;
11008
11199
  else delete ext.ferro;
11009
- if (_optionalChain([this, 'access', _779 => _779.doc, 'access', _780 => _780.magnets, 'optionalAccess', _781 => _781.length])) ext.magnets = this.doc.magnets.map((m) => ({ ...m }));
11200
+ if (_optionalChain([this, 'access', _802 => _802.doc, 'access', _803 => _803.magnets, 'optionalAccess', _804 => _804.length])) ext.magnets = this.doc.magnets.map((m) => ({ ...m }));
11010
11201
  else delete ext.magnets;
11011
- const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _782 => _782.layer])));
11202
+ const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _805 => _805.layer])));
11012
11203
  if (effectLayers) ext.effectLayers = effectLayers;
11013
11204
  else delete ext.effectLayers;
11014
11205
  if (this.doc.paperEffect) ext.paperEffect = paperEffectToJSON(this.doc.paperEffect);
@@ -11069,7 +11260,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11069
11260
  if (ext.liveStrokes && typeof ext.liveStrokes === "object") {
11070
11261
  const liveStrokes = {};
11071
11262
  for (const [id, list] of Object.entries(ext.liveStrokes)) {
11072
- if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _783 => _783.layer])) || !Array.isArray(list)) continue;
11263
+ if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _806 => _806.layer])) || !Array.isArray(list)) continue;
11073
11264
  const ok = list.map(normalizeBrushStroke).filter((x) => x !== null).map((x) => ({ ...x, layerId: id }));
11074
11265
  if (ok.length !== list.length) problems.push(`Some strokes of stroke layer "${id}" could not be read; they were dropped (the layer's pixels are kept until a stroke is edited).`);
11075
11266
  liveStrokes[id] = ok;
@@ -11079,7 +11270,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11079
11270
  if (ext.effectLayers && typeof ext.effectLayers === "object") {
11080
11271
  const effectLayers = {};
11081
11272
  for (const [id, v] of Object.entries(ext.effectLayers)) {
11082
- if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _784 => _784.layer]))) continue;
11273
+ if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _807 => _807.layer]))) continue;
11083
11274
  const source = readPaintEffectSource(v);
11084
11275
  if (source) effectLayers[id] = source;
11085
11276
  else problems.push(`The effect of layer "${id}" could not be read; it loads as a plain layer.`);
@@ -11107,7 +11298,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11107
11298
  if (ext.light && typeof ext.light === "object") {
11108
11299
  const light = {};
11109
11300
  for (const [id, v] of Object.entries(ext.light)) {
11110
- if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _785 => _785.layer]))) continue;
11301
+ if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _808 => _808.layer]))) continue;
11111
11302
  try {
11112
11303
  light[id] = lightFromJSON(v);
11113
11304
  } catch (e) {
@@ -11119,7 +11310,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11119
11310
  if (ext.fluor && typeof ext.fluor === "object") {
11120
11311
  const fluor = {};
11121
11312
  for (const [id, v] of Object.entries(ext.fluor)) {
11122
- if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _786 => _786.layer]))) continue;
11313
+ if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _809 => _809.layer]))) continue;
11123
11314
  try {
11124
11315
  fluor[id] = fluorFromJSON(v);
11125
11316
  } catch (e) {
@@ -11131,7 +11322,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11131
11322
  if (ext.thermo && typeof ext.thermo === "object") {
11132
11323
  const thermo = {};
11133
11324
  for (const [id, v] of Object.entries(ext.thermo)) {
11134
- if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _787 => _787.layer]))) continue;
11325
+ if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _810 => _810.layer]))) continue;
11135
11326
  try {
11136
11327
  thermo[id] = thermoFromJSON(v);
11137
11328
  } catch (e) {
@@ -11149,7 +11340,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11149
11340
  const ferro = {};
11150
11341
  const ferroSettings = {};
11151
11342
  for (const [id, v] of Object.entries(ext.ferro)) {
11152
- if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _788 => _788.layer]))) continue;
11343
+ if (!isPixelLayer(_optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _811 => _811.layer]))) continue;
11153
11344
  try {
11154
11345
  const loaded = ferroFromJSON(v);
11155
11346
  ferro[id] = loaded.surface;
@@ -11191,7 +11382,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11191
11382
  this.readGuides(loaded.guides, loaded.state, loaded.problems);
11192
11383
  if (Array.isArray(loaded.swatches)) this.swatches = loaded.swatches.map(readSwatch).filter((x) => x !== null);
11193
11384
  for (const s of loaded.state.strokes) {
11194
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _789 => _789.exec, 'call', _790 => _790(s.id), 'optionalAccess', _791 => _791[1]]), () => ( 0)));
11385
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _812 => _812.exec, 'call', _813 => _813(s.id), 'optionalAccess', _814 => _814[1]]), () => ( 0)));
11195
11386
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
11196
11387
  }
11197
11388
  this.undoStack = [];
@@ -11200,12 +11391,12 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11200
11391
  this.doc = this.readThick(loaded.state, loaded.extensions, loaded.problems);
11201
11392
  this.nextMagnetId = 1;
11202
11393
  for (const m of _nullishCoalesce(this.doc.magnets, () => ( []))) {
11203
- const n = Number(_nullishCoalesce(_optionalChain([/^mag(\d+)$/, 'access', _792 => _792.exec, 'call', _793 => _793(m.id), 'optionalAccess', _794 => _794[1]]), () => ( 0)));
11394
+ const n = Number(_nullishCoalesce(_optionalChain([/^mag(\d+)$/, 'access', _815 => _815.exec, 'call', _816 => _816(m.id), 'optionalAccess', _817 => _817[1]]), () => ( 0)));
11204
11395
  if (n >= this.nextMagnetId) this.nextMagnetId = n + 1;
11205
11396
  }
11206
11397
  for (const list of Object.values(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) {
11207
11398
  for (const s of list) {
11208
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _795 => _795.exec, 'call', _796 => _796(s.id), 'optionalAccess', _797 => _797[1]]), () => ( 0)));
11399
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _818 => _818.exec, 'call', _819 => _819(s.id), 'optionalAccess', _820 => _820[1]]), () => ( 0)));
11209
11400
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
11210
11401
  }
11211
11402
  }
@@ -11226,6 +11417,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11226
11417
  delete this.extensions.heat;
11227
11418
  delete this.extensions.uvLight;
11228
11419
  this.viewCompositor.clear();
11420
+ this.schemeViews.clear();
11229
11421
  this.emit();
11230
11422
  const refs = Object.values(_nullishCoalesce(this.doc.stickers, () => ( {}))).flatMap((list) => list.map((x) => x.ref));
11231
11423
  if (refs.some((r) => !_chunkRDFHWAHLcjs.editorStampOf.call(void 0, r))) void this.prepareStickers(refs).catch(() => this.emit([]));
@@ -11284,7 +11476,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11284
11476
  * pixels), and the composite as the merged image.
11285
11477
  */
11286
11478
  exportPsd() {
11287
- const driedBase = this.driedLayers(this.doc.layers);
11479
+ const driedBase = this.driedLayers(this.schemeLayers(this.doc.layers));
11288
11480
  const backlight = this.backlightLayer(driedBase);
11289
11481
  const dried = [...this.lightLayers(this.uvLayers(this.litLayers(this.thermoLayers(driedBase)))), ...backlight ? [backlight] : []];
11290
11482
  const { width, height, dpi } = this.doc.canvas;
@@ -11311,8 +11503,8 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11311
11503
  const layers = toStandard(dried);
11312
11504
  const result = _chunkQBZEC2JJcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
11313
11505
  for (const [mode, names] of changed) {
11314
- const label = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _798 => _798.find, 'call', _799 => _799((m) => m.id === mode), 'optionalAccess', _800 => _800.label]), () => ( mode));
11315
- const std = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _801 => _801.find, 'call', _802 => _802((m) => m.id === _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _803 => _803.label]), () => ( _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)));
11506
+ const label = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _821 => _821.find, 'call', _822 => _822((m) => m.id === mode), 'optionalAccess', _823 => _823.label]), () => ( mode));
11507
+ const std = _nullishCoalesce(_optionalChain([_chunk2VX55NFMcjs.BLEND_MODES, 'access', _824 => _824.find, 'call', _825 => _825((m) => m.id === _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _826 => _826.label]), () => ( _chunk2VX55NFMcjs.standardBlendMode.call(void 0, mode)));
11316
11508
  const list = names.map((n) => `"${n}"`).join(", ");
11317
11509
  const one = names.length === 1;
11318
11510
  result.warnings.push(`${label} blending has no PSD equivalent; ${list} ${one ? "was" : "were"} written as ${std}, the nearest Photoshop mode, so ${one ? "it looks" : "they look"} different in Photoshop (the merged image is exact).`);
@@ -11434,7 +11626,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11434
11626
  const { src, pixels } = this.importImage(options, "The reference image");
11435
11627
  const ref2 = {
11436
11628
  id: `ref${this.nextReferenceId++}`,
11437
- name: _optionalChain([options, 'access', _804 => _804.name, 'optionalAccess', _805 => _805.trim, 'call', _806 => _806()]) || `Reference ${this.guides.references.length + 1}`,
11629
+ name: _optionalChain([options, 'access', _827 => _827.name, 'optionalAccess', _828 => _828.trim, 'call', _829 => _829()]) || `Reference ${this.guides.references.length + 1}`,
11438
11630
  src,
11439
11631
  width: pixels.width,
11440
11632
  height: pixels.height,
@@ -11513,7 +11705,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11513
11705
  try {
11514
11706
  const px = this.decodeImage(ref2.src, `Reference "${ref2.name}"`);
11515
11707
  guides.references.push({ id: ref2.id, name: String(_nullishCoalesce(ref2.name, () => ( ref2.id))), src: ref2.src, width: px.width, height: px.height, x: Number(ref2.x) || 0, y: Number(ref2.y) || 0, displayWidth: Number(ref2.displayWidth) || 240, visible: ref2.visible !== false });
11516
- const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _807 => _807.exec, 'call', _808 => _808(ref2.id), 'optionalAccess', _809 => _809[1]]), () => ( 0)));
11708
+ const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _830 => _830.exec, 'call', _831 => _831(ref2.id), 'optionalAccess', _832 => _832[1]]), () => ( 0)));
11517
11709
  if (n >= this.nextReferenceId) this.nextReferenceId = n + 1;
11518
11710
  } catch (e) {
11519
11711
  problems.push(e.message);
@@ -11524,7 +11716,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11524
11716
  guides.stencils = [];
11525
11717
  r.stencils.forEach((raw2, i) => {
11526
11718
  try {
11527
- const id = typeof _optionalChain([raw2, 'optionalAccess', _810 => _810.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
11719
+ const id = typeof _optionalChain([raw2, 'optionalAccess', _833 => _833.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
11528
11720
  guides.stencils.push(normalizeStencil(raw2, id));
11529
11721
  const n = Number(id.slice(7));
11530
11722
  if (n >= this.nextStencilId) this.nextStencilId = n + 1;
@@ -11547,12 +11739,12 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11547
11739
  /** The next free sticker number (ids `st<n>` are unique across the document). */
11548
11740
  nextStickerNumber(doc = this.doc) {
11549
11741
  let n = 0;
11550
- for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _811 => _811.exec, 'call', _812 => _812(st.id), 'optionalAccess', _813 => _813[1]]), () => ( 0))));
11742
+ for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _834 => _834.exec, 'call', _835 => _835(st.id), 'optionalAccess', _836 => _836[1]]), () => ( 0))));
11551
11743
  return n + 1;
11552
11744
  }
11553
11745
  stickerLayer(layerId) {
11554
11746
  const l = this.wetLayer(layerId, "edit the stickers of");
11555
- const stickers = _optionalChain([this, 'access', _814 => _814.doc, 'access', _815 => _815.stickers, 'optionalAccess', _816 => _816[l.id]]);
11747
+ const stickers = _optionalChain([this, 'access', _837 => _837.doc, 'access', _838 => _838.stickers, 'optionalAccess', _839 => _839[l.id]]);
11556
11748
  if (!stickers) throw new PaintEditorError(`Layer "${l.name}" has no stickers; spray some with a sticker brush (sticker-stars; list_brush_presets lists them).`);
11557
11749
  return { layer: l, stickers };
11558
11750
  }
@@ -11628,7 +11820,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11628
11820
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
11629
11821
  if (!id) return [];
11630
11822
  this.requireLayer(id);
11631
- return (_nullishCoalesce(_optionalChain([this, 'access', _817 => _817.doc, 'access', _818 => _818.stickers, 'optionalAccess', _819 => _819[id]]), () => ( []))).map((s) => ({ ...s }));
11823
+ return (_nullishCoalesce(_optionalChain([this, 'access', _840 => _840.doc, 'access', _841 => _841.stickers, 'optionalAccess', _842 => _842[id]]), () => ( []))).map((s) => ({ ...s }));
11632
11824
  }
11633
11825
  /**
11634
11826
  * Replaces a layer's stickers and redraws its pixels from them (one undo step). With `dirty`,
@@ -11649,7 +11841,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11649
11841
  }
11650
11842
  /** The document from before the sticker preview on screen, or `null` when none is (anything else changed the document since). */
11651
11843
  previewBase() {
11652
- return _optionalChain([this, 'access', _820 => _820.stickerPreview, 'optionalAccess', _821 => _821.shown]) === this.doc ? this.stickerPreview.base : null;
11844
+ return _optionalChain([this, 'access', _843 => _843.stickerPreview, 'optionalAccess', _844 => _844.shown]) === this.doc ? this.stickerPreview.base : null;
11653
11845
  }
11654
11846
  readStickerUpdate(update) {
11655
11847
  try {
@@ -11664,7 +11856,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11664
11856
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
11665
11857
  if (!id) return null;
11666
11858
  this.requireLayer(id);
11667
- const hit = stickerAt(_nullishCoalesce(_optionalChain([this, 'access', _822 => _822.doc, 'access', _823 => _823.stickers, 'optionalAccess', _824 => _824[id]]), () => ( [])), x, y, this.stickerArt.get);
11859
+ const hit = stickerAt(_nullishCoalesce(_optionalChain([this, 'access', _845 => _845.doc, 'access', _846 => _846.stickers, 'optionalAccess', _847 => _847[id]]), () => ( [])), x, y, this.stickerArt.get);
11668
11860
  return hit ? { ...hit } : null;
11669
11861
  }
11670
11862
  /** Picks a sticker for the panel and canvas (`null` for none). Editor state, not an undo step. */
@@ -11721,8 +11913,8 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11721
11913
  const layer = this.wetLayer(layerId, "add stickers to");
11722
11914
  if (!input.length) throw new PaintEditorError("Pass at least one sticker (ref, x, y).");
11723
11915
  if (input.length > MAX_ADD_STICKERS) throw new PaintEditorError(`At most ${MAX_ADD_STICKERS} stickers per call; split them over several calls.`);
11724
- const existing = _optionalChain([this, 'access', _825 => _825.doc, 'access', _826 => _826.stickers, 'optionalAccess', _827 => _827[layer.id]]);
11725
- if (!_optionalChain([existing, 'optionalAccess', _828 => _828.length])) {
11916
+ const existing = _optionalChain([this, 'access', _848 => _848.doc, 'access', _849 => _849.stickers, 'optionalAccess', _850 => _850[layer.id]]);
11917
+ if (!_optionalChain([existing, 'optionalAccess', _851 => _851.length])) {
11726
11918
  if (this.wet.wetLayerIds().includes(layer.id) || _chunk474IQG74cjs.contentBounds.call(void 0, layer.surface)) throw new PaintEditorError(`Layer "${layer.name}" already has paint; add stickers to an empty layer (add_layer) or a sticker layer so they stay editable.`);
11727
11919
  }
11728
11920
  let n = this.nextStickerNumber();
@@ -11739,7 +11931,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11739
11931
  const id = n++;
11740
11932
  return this.withStickerVariant({ id: `st${id}`, size: 48, rotation: 0, color: this.color, opacity: 1, seed: _nullishCoalesce(raw.seed, () => ( _chunk3K6HWEXZcjs.mix32.call(void 0, id * 2654435761 >>> 0) & 2147483647)), ...u });
11741
11933
  });
11742
- this.commitStickers("Add stickers", layer, [..._nullishCoalesce(existing, () => ( [])), ...added], _optionalChain([existing, 'optionalAccess', _829 => _829.length]) ? added.map(stickerRect) : void 0);
11934
+ this.commitStickers("Add stickers", layer, [..._nullishCoalesce(existing, () => ( [])), ...added], _optionalChain([existing, 'optionalAccess', _852 => _852.length]) ? added.map(stickerRect) : void 0);
11743
11935
  return added.map((s) => ({ ...s }));
11744
11936
  }
11745
11937
  /** Brings stickers to the top (`front`) or bottom of their layer (one undo step). */
@@ -11778,20 +11970,20 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11778
11970
  }
11779
11971
  liveStrokeLayer(layerId, what) {
11780
11972
  const l = this.wetLayer(layerId, what);
11781
- const strokes = _optionalChain([this, 'access', _830 => _830.doc, 'access', _831 => _831.liveStrokes, 'optionalAccess', _832 => _832[l.id]]);
11973
+ const strokes = _optionalChain([this, 'access', _853 => _853.doc, 'access', _854 => _854.liveStrokes, 'optionalAccess', _855 => _855[l.id]]);
11782
11974
  if (!strokes) throw new PaintEditorError(`Layer "${l.name}" is not a stroke layer; add one with add_layer {type: "strokes"} (or convert_to_stroke_layer on an empty layer), then paint on it.`);
11783
11975
  return { layer: l, strokes };
11784
11976
  }
11785
11977
  /** Whether a layer is a live stroke layer. */
11786
11978
  isLiveStrokeLayer(layerId) {
11787
- return Boolean(_optionalChain([this, 'access', _833 => _833.doc, 'access', _834 => _834.liveStrokes, 'optionalAccess', _835 => _835[layerId]]));
11979
+ return Boolean(_optionalChain([this, 'access', _856 => _856.doc, 'access', _857 => _857.liveStrokes, 'optionalAccess', _858 => _858[layerId]]));
11788
11980
  }
11789
11981
  /** Makes an empty pixel layer a live stroke layer (one undo step). */
11790
11982
  convertToLiveStrokes(layerId) {
11791
11983
  this.requireIdle("converting a layer");
11792
11984
  const l = this.paintTarget(layerId, "convert");
11793
- if (_optionalChain([this, 'access', _836 => _836.doc, 'access', _837 => _837.liveStrokes, 'optionalAccess', _838 => _838[l.id]])) return this.describeLayer(l);
11794
- if (_optionalChain([this, 'access', _839 => _839.doc, 'access', _840 => _840.stickers, 'optionalAccess', _841 => _841[l.id], 'optionalAccess', _842 => _842.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; add a stroke layer instead (add_layer {type: "strokes"}).`);
11985
+ if (_optionalChain([this, 'access', _859 => _859.doc, 'access', _860 => _860.liveStrokes, 'optionalAccess', _861 => _861[l.id]])) return this.describeLayer(l);
11986
+ if (_optionalChain([this, 'access', _862 => _862.doc, 'access', _863 => _863.stickers, 'optionalAccess', _864 => _864[l.id], 'optionalAccess', _865 => _865.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; add a stroke layer instead (add_layer {type: "strokes"}).`);
11795
11987
  if (_chunk474IQG74cjs.contentBounds.call(void 0, l.surface) || this.wet.wetLayerIds().includes(l.id)) throw new PaintEditorError(`Layer "${l.name}" already has paint, which isn't kept as strokes; convert an empty layer or add a stroke layer (add_layer {type: "strokes"}).`);
11796
11988
  this.commit("Convert to stroke layer", { ...this.doc, liveStrokes: { ..._nullishCoalesce(this.doc.liveStrokes, () => ( {})), [l.id]: [] } });
11797
11989
  return this.describeLayer(this.getLayer(l.id));
@@ -11804,7 +11996,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11804
11996
  findLiveStroke(id) {
11805
11997
  for (const [layerId, strokes] of Object.entries(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) {
11806
11998
  const index = strokes.findIndex((x) => x.id === id);
11807
- const layer = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, layerId), 'optionalAccess', _843 => _843.layer]);
11999
+ const layer = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.doc.layers, layerId), 'optionalAccess', _866 => _866.layer]);
11808
12000
  if (index >= 0 && isPixelLayer(layer)) return { layer, strokes, index };
11809
12001
  }
11810
12002
  const baked = this.doc.strokes.some((x) => x.id === id);
@@ -11838,19 +12030,24 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11838
12030
  next.seed = update.seed;
11839
12031
  }
11840
12032
  if (update.color !== void 0) {
11841
- next.color = parseColor(update.color);
12033
+ const dual = typeof update.color === "string" ? null : dualHex(update.color);
12034
+ if (typeof update.color !== "string" && !dual) throw new PaintEditorError(`color ${JSON.stringify(update.color)} is not a colour; use #rrggbb, or { light, dark } with a colour each.`);
12035
+ next.color = dual ? dual.light : parseColor(update.color);
12036
+ if (dual) next.dualColor = dual;
12037
+ else delete next.dualColor;
11842
12038
  delete next.paint;
11843
12039
  }
11844
12040
  if (update.paint !== void 0) {
11845
12041
  if (update.paint === null) delete next.paint;
11846
12042
  else if (_chunkPEQWARCPcjs.isPaintEffectPaint.call(void 0, update.paint)) {
11847
- const ep = _optionalChain([update, 'access', _844 => _844.paint, 'access', _845 => _845.map, 'optionalAccess', _846 => _846.by]) === "path" ? _chunkPEQWARCPcjs.withStrokePath.call(void 0, update.paint, next.points, this.effectPathControls.get(update.paint.effect)) : update.paint;
12043
+ const ep = _optionalChain([update, 'access', _867 => _867.paint, 'access', _868 => _868.map, 'optionalAccess', _869 => _869.by]) === "path" ? _chunkPEQWARCPcjs.withStrokePath.call(void 0, update.paint, next.points, this.effectPathControls.get(update.paint.effect)) : update.paint;
11848
12044
  if (!this.effectPaintImage(ep) && !this.renderEffectPaintSync(ep)) throw new PaintEditorError(`The effect "${update.paint.effect}" is not rendered yet; render it first (prepareEffectPaints; the update_stroke tool does this).`);
11849
12045
  next.paint = JSON.parse(JSON.stringify(ep));
11850
12046
  } else {
11851
12047
  const p = this.readStrokePaint(update.paint);
11852
12048
  if (p.type === "color") {
11853
12049
  next.color = p.color;
12050
+ delete next.dualColor;
11854
12051
  delete next.paint;
11855
12052
  } else next.paint = JSON.parse(JSON.stringify(p));
11856
12053
  }
@@ -11877,7 +12074,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11877
12074
  if (edit.points !== void 0) {
11878
12075
  const points = this.checkPoints(edit.points);
11879
12076
  next = { ...was, points: points.map((p) => ({ ...p })) };
11880
- if (_optionalChain([next, 'access', _847 => _847.paint, 'optionalAccess', _848 => _848.type]) === "effect" && _optionalChain([next, 'access', _849 => _849.paint, 'access', _850 => _850.map, 'optionalAccess', _851 => _851.by]) === "path") {
12077
+ if (_optionalChain([next, 'access', _870 => _870.paint, 'optionalAccess', _871 => _871.type]) === "effect" && _optionalChain([next, 'access', _872 => _872.paint, 'access', _873 => _873.map, 'optionalAccess', _874 => _874.by]) === "path") {
11881
12078
  next.paint = _chunkPEQWARCPcjs.withStrokePath.call(void 0, next.paint, next.points, this.effectPathControls.get(next.paint.effect));
11882
12079
  }
11883
12080
  } else {
@@ -11898,9 +12095,9 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11898
12095
  const layers = /* @__PURE__ */ new Map();
11899
12096
  for (const f of found) layers.set(f.layer.id, f.layer);
11900
12097
  for (const [layerId, layer] of layers) {
11901
- const gone = (_nullishCoalesce(_optionalChain([doc, 'access', _852 => _852.liveStrokes, 'optionalAccess', _853 => _853[layerId]]), () => ( []))).filter((x) => ids.includes(x.id));
12098
+ const gone = (_nullishCoalesce(_optionalChain([doc, 'access', _875 => _875.liveStrokes, 'optionalAccess', _876 => _876[layerId]]), () => ( []))).filter((x) => ids.includes(x.id));
11902
12099
  for (const x of gone) bounds = unionRect(bounds, this.strokeArea(x));
11903
- doc = this.withLiveStrokes(doc, layer, (_nullishCoalesce(_optionalChain([doc, 'access', _854 => _854.liveStrokes, 'optionalAccess', _855 => _855[layerId]]), () => ( []))).filter((x) => !ids.includes(x.id)), this.strokeAreas(gone));
12100
+ doc = this.withLiveStrokes(doc, layer, (_nullishCoalesce(_optionalChain([doc, 'access', _877 => _877.liveStrokes, 'optionalAccess', _878 => _878[layerId]]), () => ( []))).filter((x) => !ids.includes(x.id)), this.strokeAreas(gone));
11904
12101
  }
11905
12102
  this.commit(ids.length === 1 ? "Remove stroke" : "Remove strokes", doc);
11906
12103
  return { removed: [...ids], bounds };
@@ -11966,10 +12163,15 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11966
12163
  commitLiveStrokes(label, layer, list, dirty) {
11967
12164
  this.commit(label, this.withLiveStrokes(this.doc, layer, list, dirty));
11968
12165
  }
11969
- withLiveStrokes(doc, layer, list, dirty) {
11970
- if (_chunkPVJMTLPJcjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it (update_layer locks) first.`);
11971
- const current = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, layer.id), 'optionalAccess', _856 => _856.layer]);
11972
- const hasFilm = list.some((s) => Boolean(s.brush.iridescence)) || Boolean(_optionalChain([doc, 'access', _857 => _857.thick, 'optionalAccess', _858 => _858[layer.id]]));
12166
+ /**
12167
+ * The document with a layer's strokes set and its pixels redrawn. With `record` false (the same
12168
+ * strokes drawn for the colour scheme) the pixel lock doesn't apply and no event is recorded for replays.
12169
+ */
12170
+ withLiveStrokes(doc, layer, list, dirty, options = {}) {
12171
+ const record = options.record !== false;
12172
+ if (record && _chunkPVJMTLPJcjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it (update_layer locks) first.`);
12173
+ const current = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, layer.id), 'optionalAccess', _879 => _879.layer]);
12174
+ const hasFilm = list.some((s) => Boolean(s.brush.iridescence)) || Boolean(_optionalChain([doc, 'access', _880 => _880.thick, 'optionalAccess', _881 => _881[layer.id]]));
11973
12175
  const surface = this.drawLiveStrokes(_nullishCoalesce(current, () => ( layer)), list, hasFilm ? null : dirty);
11974
12176
  let thick = doc.thick;
11975
12177
  if (hasFilm) {
@@ -11987,6 +12189,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
11987
12189
  thick = withLayerThick(doc.thick, layer.id, ch);
11988
12190
  }
11989
12191
  const next = { ...doc, layers: _chunkPVJMTLPJcjs.mapLayer.call(void 0, doc.layers, layer.id, (l) => ({ ...l, surface, offset: { x: 0, y: 0 } })), liveStrokes: { ..._nullishCoalesce(doc.liveStrokes, () => ( {})), [layer.id]: [...list] }, ...thick ? { thick } : {} };
12192
+ if (!record) return next;
11990
12193
  return this.withPaintEvent(next, { kind: "live-strokes", layerId: layer.id, data: { strokes: list.map((x) => JSON.parse(JSON.stringify(x))) } });
11991
12194
  }
11992
12195
  /** Where a stroke painted (document pixels): as learnt when it was painted or drawn, else an estimate from its points and brush. */
@@ -12066,7 +12269,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12066
12269
  if (!this.animatedLayers.size) return this.doc.layers;
12067
12270
  let layers = this.doc.layers;
12068
12271
  for (const [id, a] of this.animatedLayers) {
12069
- const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _859 => _859.layer]);
12272
+ const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _882 => _882.layer]);
12070
12273
  if (isPixelLayer(l) && l.surface === a.base) layers = _chunkPVJMTLPJcjs.mapLayer.call(void 0, layers, id, () => ({ ...l, surface: a.surface }));
12071
12274
  }
12072
12275
  return layers;
@@ -12076,7 +12279,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12076
12279
  const layers = [];
12077
12280
  const sources = /* @__PURE__ */ new Map();
12078
12281
  for (const [id, strokes] of Object.entries(_nullishCoalesce(doc.liveStrokes, () => ( {})))) {
12079
- const layer = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _860 => _860.layer]);
12282
+ const layer = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _883 => _883.layer]);
12080
12283
  const live = strokes.filter(isLiveEffect);
12081
12284
  if (!isPixelLayer(layer) || !live.length) continue;
12082
12285
  layers.push({ layer, strokes });
@@ -12201,13 +12404,13 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12201
12404
  return this.withEffectTime(time, () => this.compositePixels(options));
12202
12405
  }
12203
12406
  // --- Stencils --------------------------------------------------------------------
12204
- __init164() {this.stencilCache = null}
12205
- __init165() {this.nextStencilId = 1}
12407
+ __init167() {this.stencilCache = null}
12408
+ __init168() {this.nextStencilId = 1}
12206
12409
  /** The mask stencils' coverage over the canvas (cached), or `null` when none masks. */
12207
12410
  stencilSelection(stencils = this.guides.stencils) {
12208
12411
  const { width, height } = this.doc.canvas;
12209
12412
  const size = `${width}x${height}`;
12210
- if (_optionalChain([this, 'access', _861 => _861.stencilCache, 'optionalAccess', _862 => _862.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
12413
+ if (_optionalChain([this, 'access', _884 => _884.stencilCache, 'optionalAccess', _885 => _885.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
12211
12414
  const mask = stencilMask(stencils, width, height);
12212
12415
  this.stencilCache = { key: stencils, size, mask };
12213
12416
  return mask;
@@ -12269,7 +12472,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12269
12472
  makeSwatch(color, name) {
12270
12473
  const p = typeof color === "string" ? { type: "color", color: parseColor(color) } : this.readStrokePaint(color);
12271
12474
  const out = { color: _chunkIFWLZZCWcjs.paintSourceColor.call(void 0, p, { paint: this.color, secondary: this.secondaryColor }) };
12272
- if (_optionalChain([name, 'optionalAccess', _863 => _863.trim, 'call', _864 => _864()])) out.name = name.trim();
12475
+ if (_optionalChain([name, 'optionalAccess', _886 => _886.trim, 'call', _887 => _887()])) out.name = name.trim();
12273
12476
  if (p.type === "gradient") out.paint = p;
12274
12477
  return out;
12275
12478
  }
@@ -12321,7 +12524,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12321
12524
  * mix becomes the paint colour. Returns the mixed colour and the pile's bounds.
12322
12525
  */
12323
12526
  mixOnPad(paints2, options = {}) {
12324
- const parsed = (_nullishCoalesce(paints2, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _865 => _865.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _866 => _866.parts]) }));
12527
+ const parsed = (_nullishCoalesce(paints2, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _888 => _888.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _889 => _889.parts]) }));
12325
12528
  let r;
12326
12529
  try {
12327
12530
  r = this.pad.mix(parsed, options);
@@ -12530,7 +12733,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12530
12733
  if (m.state === "answered") throw new PaintEditorError(`Mutation "${id}" has already been answered.`);
12531
12734
  if (m.state === "declined") throw new PaintEditorError(`Mutation "${id}" was declined and cannot be answered.`);
12532
12735
  if (m.state !== "claimed") throw new PaintEditorError(`Mutation "${id}" has not been claimed yet; call read_mutation("${id}") first.`);
12533
- if (!Array.isArray(_optionalChain([input, 'optionalAccess', _867 => _867.strokes])) || !input.strokes.length) {
12736
+ if (!Array.isArray(_optionalChain([input, 'optionalAccess', _890 => _890.strokes])) || !input.strokes.length) {
12534
12737
  throw new PaintEditorError("strokes is empty; give at least one stroke with points.");
12535
12738
  }
12536
12739
  const targetLayerId = _nullishCoalesce(input.layerId, () => ( m.layerId));
@@ -12540,7 +12743,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12540
12743
  const layerId = _nullishCoalesce(s.layerId, () => ( targetLayerId));
12541
12744
  this.paintTarget(layerId, "paint on");
12542
12745
  const baseBrush = s.brushId !== void 0 ? this.requireBrush(s.brushId) : this.brush;
12543
- const stripAutoGhost = _optionalChain([baseBrush, 'access', _868 => _868.ghost, 'optionalAccess', _869 => _869.trigger]) === "agent" && !_optionalChain([s, 'access', _870 => _870.brush, 'optionalAccess', _871 => _871.ghost]);
12746
+ const stripAutoGhost = _optionalChain([baseBrush, 'access', _891 => _891.ghost, 'optionalAccess', _892 => _892.trigger]) === "agent" && !_optionalChain([s, 'access', _893 => _893.brush, 'optionalAccess', _894 => _894.ghost]);
12544
12747
  const brushPatch = {
12545
12748
  ..._nullishCoalesce(s.brush, () => ( {})),
12546
12749
  mutation: null,
@@ -12562,7 +12765,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12562
12765
  m.state = "claimed";
12563
12766
  throw e;
12564
12767
  }
12565
- const rawActorId = (_nullishCoalesce(_nullishCoalesce(_optionalChain([options, 'access', _872 => _872.actor, 'optionalAccess', _873 => _873.id]), () => ( m.claimedBy)), () => ( "mutation-agent"))).replace(/^agent:/, "") || "mutation-agent";
12768
+ const rawActorId = (_nullishCoalesce(_nullishCoalesce(_optionalChain([options, 'access', _895 => _895.actor, 'optionalAccess', _896 => _896.id]), () => ( m.claimedBy)), () => ( "mutation-agent"))).replace(/^agent:/, "") || "mutation-agent";
12566
12769
  const actor = _nullishCoalesce(options.actor, () => ( {
12567
12770
  id: rawActorId,
12568
12771
  name: "Agent",
@@ -12647,7 +12850,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12647
12850
  if (m.state === "answered") throw new PaintEditorError(`Mutation "${id}" has already been answered.`);
12648
12851
  if (m.state === "declined") return this.toMutationInfo(m);
12649
12852
  m.state = "declined";
12650
- if (_optionalChain([reason, 'optionalAccess', _874 => _874.trim, 'call', _875 => _875()])) m.declineReason = reason.trim();
12853
+ if (_optionalChain([reason, 'optionalAccess', _897 => _897.trim, 'call', _898 => _898()])) m.declineReason = reason.trim();
12651
12854
  this.keepMutationPaint(m);
12652
12855
  if (this.mutationDirector && m.claimedBy) {
12653
12856
  this.mutationDirector.presence.remove(m.claimedBy.replace(/^agent:/, "") || "mutation-agent");
@@ -12791,7 +12994,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12791
12994
  }
12792
12995
  holdMutationEvaporation(layerId) {
12793
12996
  if (this.heldEvaporation.has(layerId)) return;
12794
- const currentEvap = (_nullishCoalesce(_optionalChain([this, 'access', _876 => _876.wet, 'access', _877 => _877.settings, 'access', _878 => _878.get, 'call', _879 => _879(layerId), 'optionalAccess', _880 => _880.params]), () => ( this.wet.info(layerId).params))).evaporation;
12997
+ const currentEvap = (_nullishCoalesce(_optionalChain([this, 'access', _899 => _899.wet, 'access', _900 => _900.settings, 'access', _901 => _901.get, 'call', _902 => _902(layerId), 'optionalAccess', _903 => _903.params]), () => ( this.wet.info(layerId).params))).evaporation;
12795
12998
  this.heldEvaporation.set(layerId, currentEvap);
12796
12999
  this.wet.setParams(layerId, { evaporation: 0 });
12797
13000
  }
@@ -12845,8 +13048,8 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12845
13048
  }
12846
13049
  }
12847
13050
  mergeTempLayerIntoTarget(doc, tempLayerId, targetLayerId) {
12848
- const upper = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, tempLayerId), 'optionalAccess', _881 => _881.layer]);
12849
- const below = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, targetLayerId), 'optionalAccess', _882 => _882.layer]);
13051
+ const upper = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, tempLayerId), 'optionalAccess', _904 => _904.layer]);
13052
+ const below = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, doc.layers, targetLayerId), 'optionalAccess', _905 => _905.layer]);
12850
13053
  if (!isPixelLayer(upper)) return doc;
12851
13054
  if (!isPixelLayer(below)) {
12852
13055
  return {
@@ -12900,7 +13103,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12900
13103
  for (const m of this.mutations) {
12901
13104
  m.strokes = m.strokes.filter((s) => remainingIds.has(s.id));
12902
13105
  if (m.strokes.length === 0) {
12903
- _optionalChain([this, 'access', _883 => _883.mutationDirector, 'optionalAccess', _884 => _884.cancel, 'call', _885 => _885(m.id)]);
13106
+ _optionalChain([this, 'access', _906 => _906.mutationDirector, 'optionalAccess', _907 => _907.cancel, 'call', _908 => _908(m.id)]);
12904
13107
  if (m.claimedBy && this.mutationDirector) {
12905
13108
  this.mutationDirector.presence.remove(m.claimedBy.replace(/^agent:/, "") || "mutation-agent");
12906
13109
  }
@@ -12927,7 +13130,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12927
13130
  }
12928
13131
  resetMutations() {
12929
13132
  for (const m of this.mutations) {
12930
- _optionalChain([this, 'access', _886 => _886.mutationDirector, 'optionalAccess', _887 => _887.cancel, 'call', _888 => _888(m.id)]);
13133
+ _optionalChain([this, 'access', _909 => _909.mutationDirector, 'optionalAccess', _910 => _910.cancel, 'call', _911 => _911(m.id)]);
12931
13134
  }
12932
13135
  this.mutations = [];
12933
13136
  this.heldEvaporation.clear();
@@ -12936,11 +13139,11 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12936
13139
  }
12937
13140
  /** A layer's tile surface (live while stroking), for thumbnails. */
12938
13141
  layerSurface(id) {
12939
- const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _889 => _889.layer]);
13142
+ const l = _optionalChain([_chunkPVJMTLPJcjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _912 => _912.layer]);
12940
13143
  return isPixelLayer(l) ? l.surface : null;
12941
13144
  }
12942
13145
  // --- Proposals and evolutionary strokes ------------------------------------------
12943
- __init166() {this.proposalsStore = null}
13146
+ __init169() {this.proposalsStore = null}
12944
13147
  /** The pending paint proposals store attached to this editor (created on demand). */
12945
13148
  get proposals() {
12946
13149
  return this.proposalsStore ??= createPaintProposals({ controller: this });
@@ -12956,7 +13159,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
12956
13159
  breedStrokes(options) {
12957
13160
  const { strokeIds } = options;
12958
13161
  if (!Array.isArray(strokeIds) || strokeIds.length < 1 || strokeIds.length > 16) {
12959
- throw new PaintEditorError(`strokeIds must have 1..16 stroke ids (got ${_nullishCoalesce(_optionalChain([strokeIds, 'optionalAccess', _890 => _890.length]), () => ( 0))}); call list_strokes for the ids.`);
13162
+ throw new PaintEditorError(`strokeIds must have 1..16 stroke ids (got ${_nullishCoalesce(_optionalChain([strokeIds, 'optionalAccess', _913 => _913.length]), () => ( 0))}); call list_strokes for the ids.`);
12960
13163
  }
12961
13164
  const count = _nullishCoalesce(options.count, () => ( 4));
12962
13165
  if (!Number.isInteger(count) || count < 2 || count > 12) {
@@ -13012,7 +13215,7 @@ var PaintEditorController = (_class17 = class _PaintEditorController {
13012
13215
  breedProposal(options) {
13013
13216
  const { proposalIds } = options;
13014
13217
  if (!Array.isArray(proposalIds) || proposalIds.length < 1 || proposalIds.length > 2) {
13015
- throw new PaintEditorError(`proposalIds must have 1 or 2 proposal ids (1 to mutate, 2 to cross over; got ${_nullishCoalesce(_optionalChain([proposalIds, 'optionalAccess', _891 => _891.length]), () => ( 0))}); call list_paint_proposals for the ids.`);
13218
+ throw new PaintEditorError(`proposalIds must have 1 or 2 proposal ids (1 to mutate, 2 to cross over; got ${_nullishCoalesce(_optionalChain([proposalIds, 'optionalAccess', _914 => _914.length]), () => ( 0))}); call list_paint_proposals for the ids.`);
13016
13219
  }
13017
13220
  const count = _nullishCoalesce(options.count, () => ( 4));
13018
13221
  if (!Number.isInteger(count) || count < 2 || count > 12) {
@@ -13108,8 +13311,8 @@ function withLayerFerro(ferro, layerId, next) {
13108
13311
  }
13109
13312
  function withLayerFerroSettings(settings, ferro, layerId, next) {
13110
13313
  const out = { ..._nullishCoalesce(settings, () => ( {})) };
13111
- if (next && _optionalChain([ferro, 'optionalAccess', _892 => _892[layerId], 'optionalAccess', _893 => _893.tiles, 'access', _894 => _894.size])) out[layerId] = { amount: next.amount, wavelength: next.wavelength, threshold: next.threshold };
13112
- else if (!_optionalChain([ferro, 'optionalAccess', _895 => _895[layerId], 'optionalAccess', _896 => _896.tiles, 'access', _897 => _897.size])) delete out[layerId];
13314
+ if (next && _optionalChain([ferro, 'optionalAccess', _915 => _915[layerId], 'optionalAccess', _916 => _916.tiles, 'access', _917 => _917.size])) out[layerId] = { amount: next.amount, wavelength: next.wavelength, threshold: next.threshold };
13315
+ else if (!_optionalChain([ferro, 'optionalAccess', _918 => _918[layerId], 'optionalAccess', _919 => _919.tiles, 'access', _920 => _920.size])) delete out[layerId];
13113
13316
  return Object.keys(out).length ? out : void 0;
13114
13317
  }
13115
13318
  var BACKLIGHT_LAYER_ID = "__backlight";
@@ -13119,7 +13322,7 @@ function insertAfter(layers, id, node) {
13119
13322
  return layers.map((l) => l.type === "group" ? { ...l, children: insertAfter(l.children, id, node) } : l);
13120
13323
  }
13121
13324
  function isLiveEffect(s) {
13122
- return _optionalChain([s, 'access', _898 => _898.paint, 'optionalAccess', _899 => _899.type]) === "effect" && s.paint.live === true;
13325
+ return _optionalChain([s, 'access', _921 => _921.paint, 'optionalAccess', _922 => _922.type]) === "effect" && s.paint.live === true;
13123
13326
  }
13124
13327
  function framePaint(p, t) {
13125
13328
  return { ...p, time: p.time + t };
@@ -13144,7 +13347,7 @@ function clipRect(r, width, height) {
13144
13347
  return x1 > x0 && y1 > y0 ? { x: x0, y: y0, width: x1 - x0, height: y1 - y0 } : null;
13145
13348
  }
13146
13349
  function withLiveStroke(doc, stroke) {
13147
- const list = _optionalChain([doc, 'access', _900 => _900.liveStrokes, 'optionalAccess', _901 => _901[stroke.layerId]]);
13350
+ const list = _optionalChain([doc, 'access', _923 => _923.liveStrokes, 'optionalAccess', _924 => _924[stroke.layerId]]);
13148
13351
  return list ? { ...doc, liveStrokes: { ...doc.liveStrokes, [stroke.layerId]: [...list, stroke] } } : doc;
13149
13352
  }
13150
13353
  function shiftDocument(doc, dx, dy) {
@@ -13173,11 +13376,11 @@ function shiftDocument(doc, dx, dy) {
13173
13376
  if (doc.liveStrokes) out.liveStrokes = Object.fromEntries(Object.entries(doc.liveStrokes).map(([id, list]) => [id, list.map(moveStroke)]));
13174
13377
  if (doc.paintEvents) {
13175
13378
  out.paintEvents = doc.paintEvents.map((e) => {
13176
- const list = e.kind === "stickers" ? _optionalChain([e, 'access', _902 => _902.data, 'optionalAccess', _903 => _903.stickers]) : void 0;
13379
+ const list = e.kind === "stickers" ? _optionalChain([e, 'access', _925 => _925.data, 'optionalAccess', _926 => _926.stickers]) : void 0;
13177
13380
  if (list) return { ...e, data: { ...e.data, stickers: moveStickers(list) } };
13178
- const magnets = e.kind === "magnets" ? _optionalChain([e, 'access', _904 => _904.data, 'optionalAccess', _905 => _905.magnets]) : void 0;
13381
+ const magnets = e.kind === "magnets" ? _optionalChain([e, 'access', _927 => _927.data, 'optionalAccess', _928 => _928.magnets]) : void 0;
13179
13382
  if (magnets) return { ...e, data: { ...e.data, magnets: moveMagnets(magnets) } };
13180
- const strokes = e.kind === "live-strokes" ? _optionalChain([e, 'access', _906 => _906.data, 'optionalAccess', _907 => _907.strokes]) : void 0;
13383
+ const strokes = e.kind === "live-strokes" ? _optionalChain([e, 'access', _929 => _929.data, 'optionalAccess', _930 => _930.strokes]) : void 0;
13181
13384
  if (strokes) return { ...e, data: { ...e.data, strokes: strokes.map(moveStroke) } };
13182
13385
  if (e.kind === "fill-region" && e.data) {
13183
13386
  const d = e.data;
@@ -13264,7 +13467,7 @@ function clipToCanvas(rect, canvas) {
13264
13467
  return x1 > x0 && y1 > y0 ? { x: x0, y: y0, width: x1 - x0, height: y1 - y0 } : null;
13265
13468
  }
13266
13469
  function toEffectPaintPixels(p, pixels) {
13267
- return { width: pixels.width, height: pixels.height, data: new Uint8ClampedArray(pixels.data), ..._optionalChain([p, 'access', _908 => _908.map, 'optionalAccess', _909 => _909.by]) === "stroke" ? { map: p.map } : {} };
13470
+ return { width: pixels.width, height: pixels.height, data: new Uint8ClampedArray(pixels.data), ..._optionalChain([p, 'access', _931 => _931.map, 'optionalAccess', _932 => _932.by]) === "stroke" ? { map: p.map } : {} };
13268
13471
  }
13269
13472
  function readWetGhost(raw) {
13270
13473
  if (!raw || typeof raw !== "object") return null;
@@ -13276,6 +13479,12 @@ function readWetGhost(raw) {
13276
13479
  const linger = typeof g.linger === "number" && Number.isFinite(g.linger) ? Math.max(0.5, Math.min(60, g.linger)) : 4;
13277
13480
  return { pigment: [g.pigment[0], g.pigment[1], g.pigment[2], g.pigment[3]], remaining, total, linger };
13278
13481
  }
13482
+ function dualHex(value) {
13483
+ if (!_chunkMLLTWAXHcjs.isDualColor.call(void 0, value)) return null;
13484
+ const light = _chunkJBZRVLXVcjs.brushColourHex.call(void 0, value.light, "light");
13485
+ const dark = _chunkJBZRVLXVcjs.brushColourHex.call(void 0, value.dark, "dark");
13486
+ return light && dark ? { light, dark } : null;
13487
+ }
13279
13488
 
13280
13489
  // src/paint-editor/presence.ts
13281
13490
  var PaintPresence = class extends _chunkK7ENM55Pcjs.PresenceStore {
@@ -13294,8 +13503,8 @@ function strokeSchedule(points) {
13294
13503
  return total > 0 ? acc.map((d) => d / total) : points.map(() => 1);
13295
13504
  }
13296
13505
  function strokeDuration(points, max = 1800) {
13297
- const t0 = _optionalChain([points, 'access', _910 => _910[0], 'optionalAccess', _911 => _911.t]);
13298
- const t1 = _optionalChain([points, 'access', _912 => _912[points.length - 1], 'optionalAccess', _913 => _913.t]);
13506
+ const t0 = _optionalChain([points, 'access', _933 => _933[0], 'optionalAccess', _934 => _934.t]);
13507
+ const t1 = _optionalChain([points, 'access', _935 => _935[points.length - 1], 'optionalAccess', _936 => _936.t]);
13299
13508
  let ms;
13300
13509
  if (points.every((p) => Number.isFinite(p.t)) && t1 > t0) ms = t1 - t0;
13301
13510
  else {
@@ -13318,7 +13527,7 @@ function sweepPath(rect, rows = 4) {
13318
13527
  }
13319
13528
  var centre = (r) => ({ x: r.x + r.width / 2, y: r.y + r.height / 2 });
13320
13529
  var PaintDirector = (_class18 = class {
13321
- constructor(controller, presence, options = {}) {;_class18.prototype.__init167.call(this);_class18.prototype.__init168.call(this);
13530
+ constructor(controller, presence, options = {}) {;_class18.prototype.__init170.call(this);_class18.prototype.__init171.call(this);
13322
13531
  this.controller = controller;
13323
13532
  this.presence = presence;
13324
13533
  this.options = options;
@@ -13330,21 +13539,21 @@ var PaintDirector = (_class18 = class {
13330
13539
 
13331
13540
 
13332
13541
 
13333
- __init167() {this.cancelled = /* @__PURE__ */ new Set()}
13334
- __init168() {this.currentRun = null}
13542
+ __init170() {this.cancelled = /* @__PURE__ */ new Set()}
13543
+ __init171() {this.currentRun = null}
13335
13544
  /** Cancels any queued or running performance with `key` (e.g. a mutation that was undone). */
13336
13545
  cancel(key) {
13337
13546
  this.cancelled.add(key);
13338
- if (_optionalChain([this, 'access', _914 => _914.currentRun, 'optionalAccess', _915 => _915.key]) === key) {
13547
+ if (_optionalChain([this, 'access', _937 => _937.currentRun, 'optionalAccess', _938 => _938.key]) === key) {
13339
13548
  const { actorId, cancelSession } = this.currentRun;
13340
13549
  this.currentRun = null;
13341
- _optionalChain([cancelSession, 'optionalCall', _916 => _916()]);
13550
+ _optionalChain([cancelSession, 'optionalCall', _939 => _939()]);
13342
13551
  this.presence.remove(actorId);
13343
13552
  }
13344
13553
  }
13345
13554
  /** Acts out `commands` in order for `actor`. Resolves with one result per command. */
13346
13555
  perform(actor, commands, options) {
13347
- const key = _optionalChain([options, 'optionalAccess', _917 => _917.key]);
13556
+ const key = _optionalChain([options, 'optionalAccess', _940 => _940.key]);
13348
13557
  if (key) this.cancelled.delete(key);
13349
13558
  return this.queue.run(actor, async () => {
13350
13559
  if (key && this.cancelled.has(key)) {
@@ -13365,7 +13574,7 @@ var PaintDirector = (_class18 = class {
13365
13574
  }
13366
13575
  }
13367
13576
  } finally {
13368
- if (_optionalChain([this, 'access', _918 => _918.currentRun, 'optionalAccess', _919 => _919.key]) === key) this.currentRun = null;
13577
+ if (_optionalChain([this, 'access', _941 => _941.currentRun, 'optionalAccess', _942 => _942.key]) === key) this.currentRun = null;
13369
13578
  }
13370
13579
  return results;
13371
13580
  });
@@ -13375,7 +13584,7 @@ var PaintDirector = (_class18 = class {
13375
13584
  }
13376
13585
  where(id) {
13377
13586
  const a = this.presence.get(id);
13378
- return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _920 => _920.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _921 => _921.y]), () => ( 0)) };
13587
+ return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _943 => _943.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _944 => _944.y]), () => ( 0)) };
13379
13588
  }
13380
13589
  /** Glides to `to`; an actor that just appeared starts there instead of the corner. */
13381
13590
  async glide(id, to, ms = 380) {
@@ -13425,7 +13634,7 @@ var PaintDirector = (_class18 = class {
13425
13634
  }
13426
13635
  case "fill-region": {
13427
13636
  await this.say(id, command.note, 500);
13428
- const pts = _optionalChain([command, 'access', _922 => _922.fill, 'access', _923 => _923.points, 'optionalAccess', _924 => _924.length]) ? command.fill.points : command.fill.x !== void 0 && command.fill.y !== void 0 ? [{ x: command.fill.x, y: command.fill.y }] : [];
13637
+ const pts = _optionalChain([command, 'access', _945 => _945.fill, 'access', _946 => _946.points, 'optionalAccess', _947 => _947.length]) ? command.fill.points : command.fill.x !== void 0 && command.fill.y !== void 0 ? [{ x: command.fill.x, y: command.fill.y }] : [];
13429
13638
  for (const p of pts) {
13430
13639
  await this.glide(id, p, 240);
13431
13640
  this.presence.set({ id, pressed: true });
@@ -13436,8 +13645,8 @@ var PaintDirector = (_class18 = class {
13436
13645
  }
13437
13646
  case "replay": {
13438
13647
  await this.say(id, command.note, 500);
13439
- const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _925 => _925.replay, 'access', _926 => _926.strokeIds, 'optionalAccess', _927 => _927.includes, 'call', _928 => _928(s.id)]));
13440
- const first = _optionalChain([source, 'access', _929 => _929[0], 'optionalAccess', _930 => _930.points, 'access', _931 => _931[0]]);
13648
+ const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _948 => _948.replay, 'access', _949 => _949.strokeIds, 'optionalAccess', _950 => _950.includes, 'call', _951 => _951(s.id)]));
13649
+ const first = _optionalChain([source, 'access', _952 => _952[0], 'optionalAccess', _953 => _953.points, 'access', _954 => _954[0]]);
13441
13650
  if (first) await this.glide(id, first);
13442
13651
  const result = c.replayStrokes(command.replay);
13443
13652
  if (result.bounds) await this.glide(id, centre(result.bounds), 520);
@@ -13451,7 +13660,7 @@ var PaintDirector = (_class18 = class {
13451
13660
  const points = c.checkPoints(init.points);
13452
13661
  const { points: _points, ...rest } = init;
13453
13662
  const session = within(() => c.beginStroke({ snapToPerspective: false, start: points[0], ...rest }));
13454
- if (key && _optionalChain([this, 'access', _932 => _932.currentRun, 'optionalAccess', _933 => _933.key]) === key) {
13663
+ if (key && _optionalChain([this, 'access', _955 => _955.currentRun, 'optionalAccess', _956 => _956.key]) === key) {
13455
13664
  this.currentRun.cancelSession = () => {
13456
13665
  if (c.activeStroke === session) session.cancel();
13457
13666
  };
@@ -13485,7 +13694,7 @@ var PaintDirector = (_class18 = class {
13485
13694
  this.presence.set({ id, pressed: false });
13486
13695
  throw error;
13487
13696
  } finally {
13488
- if (key && _optionalChain([this, 'access', _934 => _934.currentRun, 'optionalAccess', _935 => _935.key]) === key) delete this.currentRun.cancelSession;
13697
+ if (key && _optionalChain([this, 'access', _957 => _957.currentRun, 'optionalAccess', _958 => _958.key]) === key) delete this.currentRun.cancelSession;
13489
13698
  }
13490
13699
  }
13491
13700
  /** Paints several strokes live in turn and commits them as one undo step (e.g. a path's subpaths). */
@@ -13495,7 +13704,7 @@ var PaintDirector = (_class18 = class {
13495
13704
  const checked = inits.map((s) => ({ ...s, points: c.checkPoints(s.points) }));
13496
13705
  const first = checked[0];
13497
13706
  const base = first.brushId ? c.getBrush(first.brushId) : c.getState().brush;
13498
- const stepLabel = _nullishCoalesce(label, () => ( `${_nullishCoalesce(_optionalChain([base, 'optionalAccess', _936 => _936.name]), () => ( "Brush"))} path stroke`));
13707
+ const stepLabel = _nullishCoalesce(label, () => ( `${_nullishCoalesce(_optionalChain([base, 'optionalAccess', _959 => _959.name]), () => ( "Brush"))} path stroke`));
13499
13708
  return c.group(stepLabel, async (within) => {
13500
13709
  let layerId = _nullishCoalesce(_nullishCoalesce(first.layerId, () => ( c.document.activeLayerId)), () => ( ""));
13501
13710
  let bounds = null;
@@ -13516,8 +13725,8 @@ var PaintDirector = (_class18 = class {
13516
13725
  bounds,
13517
13726
  dabs,
13518
13727
  strokeIds,
13519
- ..._optionalChain([last, 'optionalAccess', _937 => _937.mixerLoad]) ? { mixerLoad: last.mixerLoad } : {},
13520
- ..._optionalChain([last, 'optionalAccess', _938 => _938.wet]) !== void 0 ? { wet: last.wet } : {}
13728
+ ..._optionalChain([last, 'optionalAccess', _960 => _960.mixerLoad]) ? { mixerLoad: last.mixerLoad } : {},
13729
+ ..._optionalChain([last, 'optionalAccess', _961 => _961.wet]) !== void 0 ? { wet: last.wet } : {}
13521
13730
  };
13522
13731
  });
13523
13732
  }
@@ -14965,7 +15174,7 @@ function createMutationTools(c, options = {}) {
14965
15174
  annotations: { title: "Read and claim a mutation", ...WRITE6 },
14966
15175
  coordinates: { out: ["bounds", "strokes[].bounds", "strokes[].points[]", "cropPng.rect"] },
14967
15176
  handler: (a) => c.readMutation(a.id, {
14968
- actor: _optionalChain([options, 'access', _939 => _939.actor, 'optionalAccess', _940 => _940.id]),
15177
+ actor: _optionalChain([options, 'access', _962 => _962.actor, 'optionalAccess', _963 => _963.id]),
14969
15178
  padding: a.padding,
14970
15179
  maxSide: a.maxSide
14971
15180
  })
@@ -15150,7 +15359,7 @@ function createPaintEvolutionTools(c) {
15150
15359
  annotations: { title: "Breed stroke variants", ...WRITE7 },
15151
15360
  coordinates: { out: ["proposals[].bounds"] },
15152
15361
  handler: ({ strokeIds, count, mutation, seed }, context) => {
15153
- const actor = _optionalChain([context, 'optionalAccess', _941 => _941.actor, 'optionalAccess', _942 => _942.id]);
15362
+ const actor = _optionalChain([context, 'optionalAccess', _964 => _964.actor, 'optionalAccess', _965 => _965.id]);
15154
15363
  return c.breedStrokes({
15155
15364
  strokeIds,
15156
15365
  count,
@@ -15193,7 +15402,7 @@ function createPaintEvolutionTools(c) {
15193
15402
  annotations: { title: "Breed from paint proposals", ...WRITE7 },
15194
15403
  coordinates: { out: ["proposals[].bounds"] },
15195
15404
  handler: ({ proposalIds, count, mutation, seed }, context) => {
15196
- const actor = _optionalChain([context, 'optionalAccess', _943 => _943.actor, 'optionalAccess', _944 => _944.id]);
15405
+ const actor = _optionalChain([context, 'optionalAccess', _966 => _966.actor, 'optionalAccess', _967 => _967.id]);
15197
15406
  return c.breedProposal({
15198
15407
  proposalIds,
15199
15408
  count,
@@ -15678,7 +15887,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
15678
15887
  inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brush_presets to start from (default the active brush)." }, name: { type: "string", minLength: 1, maxLength: 80, description: "Display name." }, ..._chunkJVFGK3DKcjs.BRUSH_PATCH_PROPERTIES, unset: _chunkJVFGK3DKcjs.BRUSH_UNSET_PROPERTY }, additionalProperties: false },
15679
15888
  annotations: { title: "Set the brush", ...SET6 },
15680
15889
  handler: async ({ id, unset, ...patch }) => {
15681
- const stamps = _optionalChain([patch, 'access', _945 => _945.tip, 'optionalAccess', _946 => _946.stamps]);
15890
+ const stamps = _optionalChain([patch, 'access', _968 => _968.tip, 'optionalAccess', _969 => _969.stamps]);
15682
15891
  if (stamps) await c.prepareStickers(stamps);
15683
15892
  const r = c.setBrushFacets(patch, id, unset);
15684
15893
  return { brush: r.spec, engine: r.brush.engine, problems: r.problems };
@@ -15687,24 +15896,33 @@ function createPaintEditorToolProvider(controller, options = {}) {
15687
15896
  add({
15688
15897
  name: "set_color",
15689
15898
  title: "Set the paint colour",
15690
- description: "Sets the paint colour (and optionally the second colour) that strokes and fills use by default, and whether it is locked. Choosing a brush with a default colour (set_brush id, e.g. the highlighter's yellow) makes that the paint colour unless the colour is locked; a brush with colour.own always paints its own. Setting color goes back to one colour from gradient paint (set_paint) or effect paint (set_effect_paint). Editor state, not an undo step. Returns both colours and locked.",
15899
+ description: "Sets the paint colour (and optionally the second colour) that strokes and fills use by default, and whether it is locked. Choosing a brush with a default colour (set_brush id, e.g. the highlighter's yellow) makes that the paint colour unless the colour is locked; a brush with colour.own always paints its own. Setting color goes back to one colour from gradient paint (set_paint) or effect paint (set_effect_paint). dualColor sets a light / dark pair instead: strokes record the pair, and on a stroke layer each viewer sees them in the side of their own colour scheme (a pixel layer keeps the side painted). Editor state, not an undo step. Returns both colours and locked (and dualColor when given).",
15691
15900
  inputSchema: {
15692
15901
  type: "object",
15693
15902
  properties: {
15694
15903
  color: { ...COLOR3, description: "Paint colour #rrggbb." },
15904
+ dualColor: {
15905
+ type: "object",
15906
+ description: "A light / dark pair as the paint colour, instead of color: each side a colour #rrggbb.",
15907
+ properties: { light: { ...COLOR3, description: "The colour in the light scheme, #rrggbb." }, dark: { ...COLOR3, description: "The colour in the dark scheme, #rrggbb." } },
15908
+ required: ["light", "dark"],
15909
+ additionalProperties: false
15910
+ },
15695
15911
  secondaryColor: { ...COLOR3, description: "Second colour #rrggbb." },
15696
15912
  locked: { type: "boolean", description: "Lock the paint colour: brushes chosen later keep it instead of taking their default colour (default: unchanged; the editor starts unlocked)." }
15697
15913
  },
15698
15914
  additionalProperties: false
15699
15915
  },
15700
15916
  annotations: { title: "Set the paint colour", ...SET6 },
15701
- handler: ({ color, secondaryColor, locked }) => {
15702
- if (color === void 0 && secondaryColor === void 0 && locked === void 0) throw new Error("Pass color, secondaryColor or locked.");
15917
+ handler: ({ color, dualColor, secondaryColor, locked }) => {
15918
+ if (color === void 0 && dualColor === void 0 && secondaryColor === void 0 && locked === void 0) throw new Error("Pass color, dualColor, secondaryColor or locked.");
15919
+ if (color !== void 0 && dualColor !== void 0) throw new Error("Pass color or dualColor, not both.");
15703
15920
  if (color !== void 0) c.setColor(color);
15921
+ if (dualColor !== void 0) c.setColor(dualColor);
15704
15922
  if (secondaryColor !== void 0) c.setSecondaryColor(secondaryColor);
15705
15923
  if (locked !== void 0) c.setColorLocked(locked);
15706
15924
  const s = c.getState();
15707
- return { color: s.color, secondaryColor: s.secondaryColor, locked: s.colorLocked };
15925
+ return { color: s.color, secondaryColor: s.secondaryColor, locked: s.colorLocked, ...dualColor !== void 0 ? { dualColor: { light: dualColor.light.toLowerCase(), dark: dualColor.dark.toLowerCase() } } : {} };
15708
15926
  }
15709
15927
  });
15710
15928
  add({
@@ -15848,7 +16066,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
15848
16066
  const { path: _path, spacing: _spacing, pressure: _pressure, speed: _speed, ...stroke } = init;
15849
16067
  return {
15850
16068
  kind: "strokes",
15851
- label: `${_nullishCoalesce(_optionalChain([base, 'optionalAccess', _947 => _947.name]), () => ( "Brush"))} path stroke`,
16069
+ label: `${_nullishCoalesce(_optionalChain([base, 'optionalAccess', _970 => _970.name]), () => ( "Brush"))} path stroke`,
15852
16070
  strokes: subpaths.map((points, i) => ({
15853
16071
  ...stroke,
15854
16072
  ...stroke.seed !== void 0 ? { seed: stroke.seed + i } : {},
@@ -15905,7 +16123,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
15905
16123
  if (ids) {
15906
16124
  for (const id of ids) if (!all.some((s) => s.id === id)) throw new Error(`Unknown stroke "${id}". Call list_strokes without ids for the ids.`);
15907
16125
  }
15908
- return { total: all.length, strokes: picked.map((s) => strokeSummary(s, Boolean(ids), live ? true : liveIds.has(s.id) && _optionalChain([c, 'access', _948 => _948.document, 'access', _949 => _949.liveStrokes, 'optionalAccess', _950 => _950[s.layerId], 'optionalAccess', _951 => _951.includes, 'call', _952 => _952(s)]) === true)) };
16126
+ return { total: all.length, strokes: picked.map((s) => strokeSummary(s, Boolean(ids), live ? true : liveIds.has(s.id) && _optionalChain([c, 'access', _971 => _971.document, 'access', _972 => _972.liveStrokes, 'optionalAccess', _973 => _973[s.layerId], 'optionalAccess', _974 => _974.includes, 'call', _975 => _975(s)]) === true)) };
15909
16127
  }
15910
16128
  });
15911
16129
  add({
@@ -16218,16 +16436,16 @@ function createPaintEditorToolProvider(controller, options = {}) {
16218
16436
  }
16219
16437
  function hostTool({ coordinates, ...tool }, { origin, onChange }) {
16220
16438
  if (!origin && !onChange) return tool;
16221
- const write = !_optionalChain([tool, 'access', _953 => _953.annotations, 'optionalAccess', _954 => _954.readOnlyHint]);
16439
+ const write = !_optionalChain([tool, 'access', _976 => _976.annotations, 'optionalAccess', _977 => _977.readOnlyHint]);
16222
16440
  const done = (result) => {
16223
- if (write) _optionalChain([onChange, 'optionalCall', _955 => _955({ tool: tool.name })]);
16224
- return origin && _optionalChain([coordinates, 'optionalAccess', _956 => _956.out]) ? fromDocument(result, coordinates.out, origin) : result;
16441
+ if (write) _optionalChain([onChange, 'optionalCall', _978 => _978({ tool: tool.name })]);
16442
+ return origin && _optionalChain([coordinates, 'optionalAccess', _979 => _979.out]) ? fromDocument(result, coordinates.out, origin) : result;
16225
16443
  };
16226
16444
  return {
16227
16445
  ...tool,
16228
16446
  ...origin ? { description: hostedText(_nullishCoalesce(tool.description, () => ( ""))), inputSchema: hostedSchema(tool.inputSchema) } : {},
16229
16447
  handler: (args, context) => {
16230
- const r = tool.handler(origin && _optionalChain([coordinates, 'optionalAccess', _957 => _957.in]) ? toDocument(args, coordinates.in, origin) : args, context);
16448
+ const r = tool.handler(origin && _optionalChain([coordinates, 'optionalAccess', _980 => _980.in]) ? toDocument(args, coordinates.in, origin) : args, context);
16231
16449
  return r instanceof Promise ? r.then(done) : done(r);
16232
16450
  }
16233
16451
  };
@@ -16244,7 +16462,7 @@ function strokeSummary(s, withPoints, live) {
16244
16462
  color: s.color,
16245
16463
  points: withPoints ? s.points : s.points.length,
16246
16464
  seed: s.seed,
16247
- copies: _nullishCoalesce(_optionalChain([s, 'access', _958 => _958.copies, 'optionalAccess', _959 => _959.length]), () => ( 0)),
16465
+ copies: _nullishCoalesce(_optionalChain([s, 'access', _981 => _981.copies, 'optionalAccess', _982 => _982.length]), () => ( 0)),
16248
16466
  live,
16249
16467
  bounds: { x: Math.floor(Math.min(...xs) - pad), y: Math.floor(Math.min(...ys) - pad), width: Math.ceil(Math.max(...xs) - Math.min(...xs) + 2 * pad), height: Math.ceil(Math.max(...ys) - Math.min(...ys) + 2 * pad) }
16250
16468
  };
@@ -16254,7 +16472,7 @@ function strokeSummary(s, withPoints, live) {
16254
16472
  function paintBrushPreviewRenderer(paper = () => _chunkPEQWARCPcjs.DEFAULT_PAPER, options = {}) {
16255
16473
  const sources = new BrushSourceArtCache();
16256
16474
  const draw = (brush, { width, height, color }) => {
16257
- const stickers = _optionalChain([options, 'access', _960 => _960.stampArt, 'optionalCall', _961 => _961()]);
16475
+ const stickers = _optionalChain([options, 'access', _983 => _983.stampArt, 'optionalCall', _984 => _984()]);
16258
16476
  const stampArt = sources.with(_nullishCoalesce(stickers, () => ( (() => void 0))));
16259
16477
  const t = renderBrushThumbnail(_chunkHRUK5TFWcjs.resolveBrush.call(void 0, brush), { paper: paper(), width, height, color: color.toLowerCase(), stampArt });
16260
16478
  return { data: _chunkW5M3J7PVcjs.bytesToBase64.call(void 0, _chunkW5M3J7PVcjs.encodePng.call(void 0, t.width, t.height, t.data)), mimeType: "image/png" };
@@ -16290,22 +16508,22 @@ var PAINT_TOOLS = [
16290
16508
  { id: "rotate", label: "Rotate view", key: "r" }
16291
16509
  ];
16292
16510
  var PaintGesture = (_class19 = class {
16293
- constructor(controller, box) {;_class19.prototype.__init169.call(this);_class19.prototype.__init170.call(this);_class19.prototype.__init171.call(this);_class19.prototype.__init172.call(this);_class19.prototype.__init173.call(this);_class19.prototype.__init174.call(this);_class19.prototype.__init175.call(this);
16511
+ constructor(controller, box) {;_class19.prototype.__init172.call(this);_class19.prototype.__init173.call(this);_class19.prototype.__init174.call(this);_class19.prototype.__init175.call(this);_class19.prototype.__init176.call(this);_class19.prototype.__init177.call(this);_class19.prototype.__init178.call(this);
16294
16512
  this.controller = controller;
16295
16513
  this.box = box;
16296
16514
  }
16297
16515
 
16298
16516
 
16299
- __init169() {this.tool = "brush"}
16517
+ __init172() {this.tool = "brush"}
16300
16518
  /** Options the Fill tool (`tool === 'fill'`) passes to `fillRegion` (click to fill; drag horizontally to adjust tolerance). */
16301
- __init170() {this.fillOptions = { reference: "all", tolerance: 32, closeGap: 4, expand: 1, antialias: true }}
16519
+ __init173() {this.fillOptions = { reference: "all", tolerance: 32, closeGap: 4, expand: 1, antialias: true }}
16302
16520
  /** The last refusal (a hidden or locked layer), for the editor to show. */
16303
- __init171() {this.error = null}
16521
+ __init174() {this.error = null}
16304
16522
  /** The predicted tail of the current stroke in document pixels (draw it as a thin preview). */
16305
- __init172() {this.predicted = []}
16306
- __init173() {this.mode = null}
16307
- __init174() {this.penAt = null}
16308
- __init175() {this.penDown = false}
16523
+ __init175() {this.predicted = []}
16524
+ __init176() {this.mode = null}
16525
+ __init177() {this.penAt = null}
16526
+ __init178() {this.penDown = false}
16309
16527
  doc(e) {
16310
16528
  const b = this.box();
16311
16529
  const s = this.controller.getState();
@@ -16362,13 +16580,13 @@ var PaintGesture = (_class19 = class {
16362
16580
  const p = this.doc(e);
16363
16581
  const s = this.controller.getState();
16364
16582
  const layerId = s.document.activeLayerId;
16365
- if (!layerId || !_optionalChain([s, 'access', _962 => _962.document, 'access', _963 => _963.liveStrokes, 'optionalAccess', _964 => _964[layerId]])) {
16583
+ if (!layerId || !_optionalChain([s, 'access', _985 => _985.document, 'access', _986 => _986.liveStrokes, 'optionalAccess', _987 => _987[layerId]])) {
16366
16584
  this.error = "Pick a stroke layer in the Layers panel (or add one) to select its strokes.";
16367
16585
  return false;
16368
16586
  }
16369
16587
  try {
16370
16588
  const hit = this.controller.liveStrokeAt(layerId, p.x, p.y);
16371
- this.controller.selectStroke(_nullishCoalesce(_optionalChain([hit, 'optionalAccess', _965 => _965.id]), () => ( null)));
16589
+ this.controller.selectStroke(_nullishCoalesce(_optionalChain([hit, 'optionalAccess', _988 => _988.id]), () => ( null)));
16372
16590
  if (!hit) return false;
16373
16591
  this.mode = { kind: "move-stroke", pointerId: e.pointerId, id: hit.id, from: p, to: p };
16374
16592
  return true;
@@ -16380,7 +16598,7 @@ var PaintGesture = (_class19 = class {
16380
16598
  /** While a stroke is dragged: how far it has moved (document pixels), to draw its outline there. */
16381
16599
  get strokeDrag() {
16382
16600
  const m = this.mode;
16383
- return _optionalChain([m, 'optionalAccess', _966 => _966.kind]) === "move-stroke" ? { id: m.id, dx: m.to.x - m.from.x, dy: m.to.y - m.from.y } : null;
16601
+ return _optionalChain([m, 'optionalAccess', _989 => _989.kind]) === "move-stroke" ? { id: m.id, dx: m.to.x - m.from.x, dy: m.to.y - m.from.y } : null;
16384
16602
  }
16385
16603
  /**
16386
16604
  * The Stickers tool: pressing a sticker picks it and dragging moves it (one undo step at the
@@ -16482,8 +16700,8 @@ var PaintGesture = (_class19 = class {
16482
16700
  this.mode = null;
16483
16701
  this.predicted = [];
16484
16702
  if (m.kind === "stroke") {
16485
- _optionalChain([this, 'access', _967 => _967.controller, 'access', _968 => _968.activeStroke, 'optionalAccess', _969 => _969.end, 'call', _970 => _970()]);
16486
- _optionalChain([this, 'access', _971 => _971.controller, 'access', _972 => _972.strokeRendering, 'optionalAccess', _973 => _973.catch, 'call', _974 => _974((err) => {
16703
+ _optionalChain([this, 'access', _990 => _990.controller, 'access', _991 => _991.activeStroke, 'optionalAccess', _992 => _992.end, 'call', _993 => _993()]);
16704
+ _optionalChain([this, 'access', _994 => _994.controller, 'access', _995 => _995.strokeRendering, 'optionalAccess', _996 => _996.catch, 'call', _997 => _997((err) => {
16487
16705
  this.error = err instanceof Error ? err.message : String(err);
16488
16706
  })]);
16489
16707
  }
@@ -16518,9 +16736,9 @@ var PaintGesture = (_class19 = class {
16518
16736
  cancel() {
16519
16737
  this.penDown = false;
16520
16738
  this.predicted = [];
16521
- if (_optionalChain([this, 'access', _975 => _975.mode, 'optionalAccess', _976 => _976.kind]) === "stroke") _optionalChain([this, 'access', _977 => _977.controller, 'access', _978 => _978.activeStroke, 'optionalAccess', _979 => _979.cancel, 'call', _980 => _980()]);
16522
- if (_optionalChain([this, 'access', _981 => _981.mode, 'optionalAccess', _982 => _982.kind]) === "fill" && this.mode.committed) this.controller.undo();
16523
- if (_optionalChain([this, 'access', _983 => _983.mode, 'optionalAccess', _984 => _984.kind]) === "sticker") this.controller.cancelStickerPreview();
16739
+ if (_optionalChain([this, 'access', _998 => _998.mode, 'optionalAccess', _999 => _999.kind]) === "stroke") _optionalChain([this, 'access', _1000 => _1000.controller, 'access', _1001 => _1001.activeStroke, 'optionalAccess', _1002 => _1002.cancel, 'call', _1003 => _1003()]);
16740
+ if (_optionalChain([this, 'access', _1004 => _1004.mode, 'optionalAccess', _1005 => _1005.kind]) === "fill" && this.mode.committed) this.controller.undo();
16741
+ if (_optionalChain([this, 'access', _1006 => _1006.mode, 'optionalAccess', _1007 => _1007.kind]) === "sticker") this.controller.cancelStickerPreview();
16524
16742
  this.mode = null;
16525
16743
  }
16526
16744
  get active() {
@@ -16585,13 +16803,13 @@ function handlePaintShortcut(controller, gesture, e) {
16585
16803
  return true;
16586
16804
  }
16587
16805
  var PaintCanvasPresenter = (_class20 = class {
16588
- constructor(controller) {;_class20.prototype.__init176.call(this);_class20.prototype.__init177.call(this);_class20.prototype.__init178.call(this);
16806
+ constructor(controller) {;_class20.prototype.__init179.call(this);_class20.prototype.__init180.call(this);_class20.prototype.__init181.call(this);
16589
16807
  this.controller = controller;
16590
16808
  }
16591
16809
 
16592
- __init176() {this.uploaded = /* @__PURE__ */ new Map()}
16593
- __init177() {this.scratch = null}
16594
- __init178() {this.size = ""}
16810
+ __init179() {this.uploaded = /* @__PURE__ */ new Map()}
16811
+ __init180() {this.scratch = null}
16812
+ __init181() {this.size = ""}
16595
16813
  /** Draws what changed into `ctx` (a canvas the size of the document); returns the tiles drawn. */
16596
16814
  render(ctx) {
16597
16815
  const { width, height } = this.controller.document.canvas;
@@ -16623,7 +16841,7 @@ function guideOverlay(controller, drag) {
16623
16841
  const size = s.document.canvas;
16624
16842
  const out = [];
16625
16843
  const layerId = s.document.activeLayerId;
16626
- const strokePicked = layerId && s.selectedStroke ? _optionalChain([s, 'access', _985 => _985.document, 'access', _986 => _986.liveStrokes, 'optionalAccess', _987 => _987[layerId], 'optionalAccess', _988 => _988.some, 'call', _989 => _989((x) => x.id === s.selectedStroke)]) : false;
16844
+ const strokePicked = layerId && s.selectedStroke ? _optionalChain([s, 'access', _1008 => _1008.document, 'access', _1009 => _1009.liveStrokes, 'optionalAccess', _1010 => _1010[layerId], 'optionalAccess', _1011 => _1011.some, 'call', _1012 => _1012((x) => x.id === s.selectedStroke)]) : false;
16627
16845
  const area = strokePicked ? controller.liveStrokeArea(s.selectedStroke) : null;
16628
16846
  if (area) {
16629
16847
  const dx = drag && drag.id === s.selectedStroke ? drag.dx : 0;
@@ -16636,7 +16854,7 @@ function guideOverlay(controller, drag) {
16636
16854
  ];
16637
16855
  for (let i = 0; i < 4; i++) out.push({ from: box[i], to: box[(i + 1) % 4], kind: "stroke" });
16638
16856
  }
16639
- const picked = layerId && s.selectedSticker ? _optionalChain([s, 'access', _990 => _990.document, 'access', _991 => _991.stickers, 'optionalAccess', _992 => _992[layerId], 'optionalAccess', _993 => _993.find, 'call', _994 => _994((x) => x.id === s.selectedSticker)]) : void 0;
16857
+ const picked = layerId && s.selectedSticker ? _optionalChain([s, 'access', _1013 => _1013.document, 'access', _1014 => _1014.stickers, 'optionalAccess', _1015 => _1015[layerId], 'optionalAccess', _1016 => _1016.find, 'call', _1017 => _1017((x) => x.id === s.selectedSticker)]) : void 0;
16640
16858
  if (picked) {
16641
16859
  const r = picked.size / 2 + 2;
16642
16860
  const a = picked.rotation * Math.PI / 180;
@@ -16666,7 +16884,7 @@ var PAPER_SLIDERS = [
16666
16884
  ];
16667
16885
  function readPath(obj, path) {
16668
16886
  let v = obj;
16669
- for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _995 => _995[k]]);
16887
+ for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _1018 => _1018[k]]);
16670
16888
  return typeof v === "number" ? v : 0;
16671
16889
  }
16672
16890
  function patchPath(obj, path, value) {
@@ -16794,7 +17012,7 @@ function startWetClock(controller, frame, cancel) {
16794
17012
  id = raf(loop);
16795
17013
  return () => {
16796
17014
  stopped = true;
16797
- _optionalChain([caf, 'optionalCall', _996 => _996(id)]);
17015
+ _optionalChain([caf, 'optionalCall', _1019 => _1019(id)]);
16798
17016
  };
16799
17017
  }
16800
17018
  function drawWaterOverlay(controller, ctx) {
@@ -16861,7 +17079,7 @@ function startDeviceTilt(controller) {
16861
17079
  };
16862
17080
  g.addEventListener("deviceorientation", onOrientation);
16863
17081
  return () => {
16864
- _optionalChain([g, 'access', _997 => _997.removeEventListener, 'optionalCall', _998 => _998("deviceorientation", onOrientation)]);
17082
+ _optionalChain([g, 'access', _1020 => _1020.removeEventListener, 'optionalCall', _1021 => _1021("deviceorientation", onOrientation)]);
16865
17083
  };
16866
17084
  }
16867
17085
  var PARTICLE_KIND_LABELS = { string: "Strings", spring: "Springs", orbit: "Orbits", flow: "Flow", elastic: "Elastic", fuzzy: "Fuzzy" };
@@ -17279,7 +17497,7 @@ function createPaintProposalToolProvider(proposals, options = {}) {
17279
17497
  },
17280
17498
  annotations: { title: "Propose paint", ...WRITE9 },
17281
17499
  handler: (args, context) => {
17282
- const origin = _optionalChain([context, 'access', _999 => _999.actor, 'optionalAccess', _1000 => _1000.id]) ? `agent:${context.actor.id}` : options.fallbackOrigin;
17500
+ const origin = _optionalChain([context, 'access', _1022 => _1022.actor, 'optionalAccess', _1023 => _1023.id]) ? `agent:${context.actor.id}` : options.fallbackOrigin;
17283
17501
  const proposal = proposals.propose({ ...args, ...origin ? { origin } : {} });
17284
17502
  const { id: _id, missing: _missing, createdAt: _createdAt, ...rest } = describe(proposal);
17285
17503
  return { proposalId: proposal.id, ...rest };
@@ -18016,4 +18234,5 @@ function createPaintConformanceHost(setup, options) {
18016
18234
 
18017
18235
 
18018
18236
 
18019
- exports.BACKLIGHT_SPILL = BACKLIGHT_SPILL; exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunk2VX55NFMcjs.BLEND_MODES; exports.BRUSH_ID = _chunkHRUK5TFWcjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunkHRUK5TFWcjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = _chunkJVFGK3DKcjs.BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunkHRUK5TFWcjs.BUILTIN_BRUSHES; exports.BristleStroke = BristleStroke; exports.BrushSourceArtCache = BrushSourceArtCache; exports.DAB_FLIPS = _chunkHRUK5TFWcjs.DAB_FLIPS; exports.DEFAULT_BACKLIGHT_COLOR = DEFAULT_BACKLIGHT_COLOR; exports.DEFAULT_BEHAVIOR = _chunkHRUK5TFWcjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunkHRUK5TFWcjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunkHRUK5TFWcjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunkHRUK5TFWcjs.DEFAULT_DYNAMICS; exports.DEFAULT_FERRO = _chunkHRUK5TFWcjs.DEFAULT_FERRO; exports.DEFAULT_FLOW = _chunkMITQGHN3cjs.DEFAULT_FLOW; exports.DEFAULT_FLUORESCENCE = _chunkHRUK5TFWcjs.DEFAULT_FLUORESCENCE; exports.DEFAULT_GHOST = _chunkHRUK5TFWcjs.DEFAULT_GHOST; exports.DEFAULT_IMPASTO = _chunkHRUK5TFWcjs.DEFAULT_IMPASTO; exports.DEFAULT_IRIDESCENCE = _chunkHRUK5TFWcjs.DEFAULT_IRIDESCENCE; exports.DEFAULT_LIGHT = _chunkHRUK5TFWcjs.DEFAULT_LIGHT; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_LIVE_PATTERNS = _chunkIFWLZZCWcjs.DEFAULT_LIVE_PATTERNS; exports.DEFAULT_MAGNET_RADIUS = DEFAULT_MAGNET_RADIUS; exports.DEFAULT_MAGNET_STRENGTH = DEFAULT_MAGNET_STRENGTH; exports.DEFAULT_MULTI_COLOR = _chunkHRUK5TFWcjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_MUTATION = _chunkHRUK5TFWcjs.DEFAULT_MUTATION; exports.DEFAULT_MUTATION_RATES = DEFAULT_MUTATION_RATES; exports.DEFAULT_PAINT_GRADIENT = _chunkIFWLZZCWcjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkIFWLZZCWcjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = _chunkPEQWARCPcjs.DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunkHRUK5TFWcjs.DEFAULT_PARTICLE; exports.DEFAULT_SPRAY = _chunkHRUK5TFWcjs.DEFAULT_SPRAY; exports.DEFAULT_STICKER = _chunkHRUK5TFWcjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_THERMOCHROMIC = _chunkHRUK5TFWcjs.DEFAULT_THERMOCHROMIC; exports.DEFAULT_TIP_GRAIN = _chunkHRUK5TFWcjs.DEFAULT_TIP_GRAIN; exports.DEFAULT_UV_LIGHT = DEFAULT_UV_LIGHT; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_VIEW_TILT = DEFAULT_VIEW_TILT; exports.DEFAULT_WET_BRUSH = _chunkHRUK5TFWcjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkMITQGHN3cjs.DEFAULT_WET_PARAMS; exports.DOT_ROTATIONS = _chunkHRUK5TFWcjs.DOT_ROTATIONS; exports.DOT_ROTATION_LABELS = DOT_ROTATION_LABELS; exports.DOT_TEXTURE_ORDERS = _chunkHRUK5TFWcjs.DOT_TEXTURE_ORDERS; exports.DOT_TEXTURE_ORDER_LABELS = DOT_TEXTURE_ORDER_LABELS; exports.DryStroke = _chunkPEQWARCPcjs.DryStroke; exports.EFFECT_MAP_REPEATS = _chunkPEQWARCPcjs.EFFECT_MAP_REPEATS; exports.EFFECT_STRIP_HEIGHT = _chunkPEQWARCPcjs.EFFECT_STRIP_HEIGHT; exports.EVOLUTION_BRUSH_FACETS = EVOLUTION_BRUSH_FACETS; exports.EVOLUTION_MUTATION_SCHEMA = EVOLUTION_MUTATION_SCHEMA; exports.EVOLUTION_SLIDERS = EVOLUTION_SLIDERS; exports.FERRO_CARRIER_RGB = FERRO_CARRIER_RGB; exports.FERRO_DEFAULT_GLOSS = FERRO_DEFAULT_GLOSS; exports.FERRO_DEFAULT_METALLIC = FERRO_DEFAULT_METALLIC; exports.FERRO_DEFAULT_RIM = FERRO_DEFAULT_RIM; exports.FilmBuffer = FilmBuffer; exports.GHOST_SLIDERS = _chunkJVFGK3DKcjs.GHOST_SLIDERS; exports.GHOST_TRIGGERS = _chunkHRUK5TFWcjs.GHOST_TRIGGERS; exports.GPU_LEAD = _chunkPEQWARCPcjs.GPU_LEAD; exports.GRAIN_PATTERNS = _chunkIFWLZZCWcjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkIFWLZZCWcjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunkI3Y2Q3PMcjs.HARMONY_KINDS; exports.HEAT_COOLING = HEAT_COOLING; exports.HEAT_DIFFUSION = HEAT_DIFFUSION; exports.HEAT_DRY_THRESHOLD = HEAT_DRY_THRESHOLD; exports.HEAT_SCALE = HEAT_SCALE; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = _chunkPEQWARCPcjs.IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunkHRUK5TFWcjs.IMPASTO_TOOLS; exports.IMPASTO_TOOL_LABELS = IMPASTO_TOOL_LABELS; exports.IRIDESCENCE_SLIDERS = _chunkJVFGK3DKcjs.IRIDESCENCE_SLIDERS; exports.LIGHT_SLIDERS = LIGHT_SLIDERS; exports.LIVE_PATTERN_KINDS = _chunkIFWLZZCWcjs.LIVE_PATTERN_KINDS; exports.LIVE_PATTERN_LABELS = LIVE_PATTERN_LABELS; exports.LIVE_PATTERN_PRESETS = _chunkIFWLZZCWcjs.LIVE_PATTERN_PRESETS; exports.LIVE_PATTERN_SCHEMA = LIVE_PATTERN_SCHEMA; exports.LIVE_PATTERN_SLIDERS = LIVE_PATTERN_SLIDERS; exports.LIVE_STROKE_ENGINES = LIVE_STROKE_ENGINES; exports.LitCache = LitCache; exports.MAGNET_SLIDERS = MAGNET_SLIDERS; exports.MAX_BRUSH_SIZE = _chunkIFWLZZCWcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_DOT_TEXTURES = _chunkHRUK5TFWcjs.MAX_DOT_TEXTURES; exports.MAX_EFFECT_PATH_POINTS = _chunkPEQWARCPcjs.MAX_EFFECT_PATH_POINTS; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_LIVE_EFFECT_SOURCES = MAX_LIVE_EFFECT_SOURCES; exports.MAX_PATH_SAMPLES = MAX_PATH_SAMPLES; exports.MAX_STICKER_STAMPS = _chunkHRUK5TFWcjs.MAX_STICKER_STAMPS; exports.MAX_ZOOM = MAX_ZOOM; exports.MIN_CANVAS_SIDE = MIN_CANVAS_SIDE; exports.MIN_ZOOM = MIN_ZOOM; exports.MIXING_PAD_HEIGHT = MIXING_PAD_HEIGHT; exports.MIXING_PAD_WIDTH = MIXING_PAD_WIDTH; exports.MULTI_COLOR_MODES = _chunkHRUK5TFWcjs.MULTI_COLOR_MODES; exports.MUTATION_SLIDERS = _chunkJVFGK3DKcjs.MUTATION_SLIDERS; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunk2VX55NFMcjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunkHRUK5TFWcjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunkHRUK5TFWcjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkIFWLZZCWcjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_CONTRACT_FORMAT_VERSION = PAINT_CONTRACT_FORMAT_VERSION; exports.PAINT_DOCUMENT_JSON_SCHEMA = PAINT_DOCUMENT_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkIFWLZZCWcjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkIFWLZZCWcjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkIFWLZZCWcjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkIFWLZZCWcjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SHORTCUTS = PAINT_SHORTCUTS; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkIFWLZZCWcjs.PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_TARGET = PAINT_TARGET; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_EFFECT_BLENDS = PAPER_EFFECT_BLENDS; exports.PAPER_EFFECT_NODE_ID = PAPER_EFFECT_NODE_ID; exports.PAPER_FAMILIES = _chunkPEQWARCPcjs.PAPER_FAMILIES; exports.PAPER_LIBRARY = _chunkPEQWARCPcjs.PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunkHRUK5TFWcjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunkHRUK5TFWcjs.PARTICLE_RENDERS; exports.PARTICLE_RENDER_LABELS = PARTICLE_RENDER_LABELS; exports.PATH_STROKE_TAPERS = PATH_STROKE_TAPERS; exports.PaintCanvasPresenter = PaintCanvasPresenter; exports.PaintDabStroke = _chunkPEQWARCPcjs.PaintDabStroke; exports.PaintDirector = PaintDirector; exports.PaintDocumentError = PaintDocumentError; exports.PaintEditorController = PaintEditorController; exports.PaintEditorError = PaintEditorError; exports.PaintEffectsRenderer = PaintEffectsRenderer; exports.PaintGesture = PaintGesture; exports.PaintGradientSampler = _chunkIFWLZZCWcjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkIFWLZZCWcjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = _chunkPEQWARCPcjs.PaintWetLayers; exports.PaperGrain = _chunkIFWLZZCWcjs.PaperGrain; exports.ParticleStroke = ParticleStroke; exports.PenDabWalker = _chunkPEQWARCPcjs.PenDabWalker; exports.PenSmoother = _chunkPEQWARCPcjs.PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.RIBBON_PAIRS = _chunkHRUK5TFWcjs.RIBBON_PAIRS; exports.RIBBON_PAIR_LABELS = RIBBON_PAIR_LABELS; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunkRDFHWAHLcjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_ART_SIZE = STICKER_ART_SIZE; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.STROKE_SLIDERS = STROKE_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerArtCache = StickerArtCache; exports.StickerBrowser = _chunk3VHH6V67cjs.StickerBrowser; exports.StickerSpray = StickerSpray; exports.TIP_GRAIN_MODES = _chunkHRUK5TFWcjs.TIP_GRAIN_MODES; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThermoCache = ThermoCache; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunk3K6HWEXZcjs.TileableNoise; exports.TipGrain = _chunkPEQWARCPcjs.TipGrain; exports.UV_LIGHT_SLIDERS = UV_LIGHT_SLIDERS; exports.UvCache = UvCache; exports.VIEW_TILT_SLIDERS = VIEW_TILT_SLIDERS; exports.WET_FLOW_KINDS = _chunkMITQGHN3cjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = _chunkPEQWARCPcjs.WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunkHRUK5TFWcjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = _chunkPEQWARCPcjs.WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkMITQGHN3cjs.WET_PARAM_KEYS; exports.WET_PARAM_SCHEMA = WET_PARAM_SCHEMA; exports.WET_PARAM_SLIDERS = WET_PARAM_SLIDERS; exports.WET_SPEED_SLIDER = WET_SPEED_SLIDER; exports.WET_TILT_SLIDERS = WET_TILT_SLIDERS; exports.WET_TOOLS = _chunkHRUK5TFWcjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = _chunkPEQWARCPcjs.WetStrokeDriver; exports.addPaintGradientStop = _chunkIFWLZZCWcjs.addPaintGradientStop; exports.addPolygonArea = addPolygonArea; exports.advanceHeatField = advanceHeatField; exports.advectFerro = advectFerro; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.backlightOf = backlightOf; exports.bakeFerroIntoThick = bakeFerroIntoThick; exports.brushEngineControls = _chunkJVFGK3DKcjs.brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunkHRUK5TFWcjs.brushTakesPaint; exports.brushToJSON = _chunkHRUK5TFWcjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkEvolutionStrokes = checkEvolutionStrokes; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clearHeatField = clearHeatField; exports.cloneHeatField = cloneHeatField; exports.clonePaper = _chunkPEQWARCPcjs.clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.computeUvSpill = computeUvSpill; exports.contactSheet = contactSheet; exports.createEvolutionTools = createEvolutionTools; exports.createFerroTools = createFerroTools; exports.createHeatField = createHeatField; exports.createMutationTools = createMutationTools; exports.createPaintAgentStrokes = createPaintAgentStrokes; exports.createPaintBrushLibraryToolProvider = createPaintBrushLibraryToolProvider; exports.createPaintChangeFeed = createPaintChangeFeed; exports.createPaintCompositor = createPaintCompositor; exports.createPaintConformanceHost = createPaintConformanceHost; exports.createPaintDocument = createPaintDocument; exports.createPaintEditorDocument = createPaintEditorDocument; exports.createPaintEditorToolProvider = createPaintEditorToolProvider; exports.createPaintEffectsToolProvider = createPaintEffectsToolProvider; exports.createPaintEvolutionToolProvider = createPaintEvolutionToolProvider; exports.createPaintEvolutionTools = createPaintEvolutionTools; exports.createPaintLayer = createPaintLayer; exports.createPaintProposalToolProvider = createPaintProposalToolProvider; exports.createPaintProposals = createPaintProposals; exports.createPaintReplayTools = createPaintReplayTools; exports.createPaintStickerTools = createPaintStickerTools; exports.createPaintThickTools = createPaintThickTools; exports.createPaintWetTools = createPaintWetTools; exports.crossoverBrushes = crossoverBrushes; exports.crossoverGenomes = crossoverGenomes; exports.crossoverStrokes = crossoverStrokes; exports.decodeImageBlob = decodeImageBlob; exports.defaultGuides = defaultGuides; exports.defaultImageEncoder = defaultImageEncoder; exports.defaultStickerRasterizer = defaultStickerRasterizer; exports.describeGenomeDiff = describeGenomeDiff; exports.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.deviceOrientationToViewTilt = deviceOrientationToViewTilt; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.drawSticker = drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.driftBrushFacets = driftBrushFacets; exports.driftColorOklch = driftColorOklch; exports.effectDabField = _chunkPEQWARCPcjs.effectDabField; exports.effectLayersToJSON = effectLayersToJSON; exports.effectPaintKey = _chunkPEQWARCPcjs.effectPaintKey; exports.effectPaintSize = _chunkPEQWARCPcjs.effectPaintSize; exports.emptiedLayers = emptiedLayers; exports.emptyFerro = emptyFerro; exports.emptyFluor = emptyFluor; exports.emptyThermo = emptyThermo; exports.emptyThickChannels = emptyThickChannels; exports.engineBrushSourceIds = engineBrushSourceIds; exports.exportProposalContactSheetPng = exportProposalContactSheetPng; exports.ferroCacheKey = ferroCacheKey; exports.ferroFieldAt = ferroFieldAt; exports.ferroFromJSON = ferroFromJSON; exports.ferroInfo = ferroInfo; exports.ferroSpikeHeightAt = ferroSpikeHeightAt; exports.ferroToJSON = ferroToJSON; exports.ferroToShadow = ferroToShadow; exports.ferroTwinBrush = ferroTwinBrush; exports.fillRegionMask = _chunkYH6SKC7Pcjs.fillRegionMask; exports.finalizeThermoStroke = finalizeThermoStroke; exports.findUnfilledRegionsMask = _chunkYH6SKC7Pcjs.findUnfilledRegionsMask; exports.fitZoom = fitZoom; exports.fluorFromJSON = fluorFromJSON; exports.fluorToJSON = fluorToJSON; exports.fluorTwinBrush = fluorTwinBrush; exports.grainCatch = _chunkIFWLZZCWcjs.grainCatch; exports.grainHeights = _chunkIFWLZZCWcjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hasThickChannels = hasThickChannels; exports.hash2 = _chunk3K6HWEXZcjs.hash2; exports.heatFromJSON = heatFromJSON; exports.heatStats = heatStats; exports.heatToJSON = heatToJSON; exports.hexToPaintRgb = _chunkIFWLZZCWcjs.hexToPaintRgb; exports.hexToRgb8 = _chunkPEQWARCPcjs.hexToRgb8; exports.hotCellsBounds = hotCellsBounds; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunkI3Y2Q3PMcjs.hueToWheel; exports.inferEffectPathControl = _chunkPEQWARCPcjs.inferEffectPathControl; exports.invertAffine = invertAffine; exports.isBlendMode = _chunk2VX55NFMcjs.isBlendMode; exports.isGradientPaint = _chunkIFWLZZCWcjs.isGradientPaint; exports.isPaintEffectPaint = _chunkPEQWARCPcjs.isPaintEffectPaint; exports.isPainterlyBlendMode = _chunk2VX55NFMcjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunkHRUK5TFWcjs.isWetBrush; exports.isWetCapable = _chunkHRUK5TFWcjs.isWetCapable; exports.jitterStrokePoints = jitterStrokePoints; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.liveStrokeBounds = liveStrokeBounds; exports.liveStrokeRefusal = liveStrokeRefusal; exports.magnetsFromJSON = magnetsFromJSON; exports.mapPenPoint = mapPenPoint; exports.mergeFerro = mergeFerro; exports.mergeFourChannel = mergeFourChannel; exports.mix32 = _chunk3K6HWEXZcjs.mix32; exports.mixColorOklch = mixColorOklch; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = _chunkPEQWARCPcjs.mixerTip; exports.multiColorForDab = _chunkPEQWARCPcjs.multiColorForDab; exports.multiColorGradient = _chunkPEQWARCPcjs.multiColorGradient; exports.multiColorPalette = _chunkPEQWARCPcjs.multiColorPalette; exports.multiColorSliders = _chunkJVFGK3DKcjs.multiColorSliders; exports.multiColorToPaint = _chunkHRUK5TFWcjs.multiColorToPaint; exports.mutateGenome = mutateGenome; exports.mutateStroke = mutateStroke; exports.mutationBrushRefusal = mutationBrushRefusal; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunkHRUK5TFWcjs.normalizeBehavior; exports.normalizeBristle = _chunkHRUK5TFWcjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunkHRUK5TFWcjs.normalizeDynamics; exports.normalizeFerro = _chunkHRUK5TFWcjs.normalizeFerro; exports.normalizeFerroSettings = _chunkHRUK5TFWcjs.normalizeFerro; exports.normalizeFlow = _chunkMITQGHN3cjs.normalizeFlow; exports.normalizeFluorescence = _chunkHRUK5TFWcjs.normalizeFluorescence; exports.normalizeGhost = _chunkHRUK5TFWcjs.normalizeGhost; exports.normalizeHexColor = _chunkIFWLZZCWcjs.normalizeHexColor; exports.normalizeImpasto = _chunkHRUK5TFWcjs.normalizeImpasto; exports.normalizeLight = _chunkHRUK5TFWcjs.normalizeLight; exports.normalizeLighting = normalizeLighting; exports.normalizeLivePatterns = _chunkIFWLZZCWcjs.normalizeLivePatterns; exports.normalizeMagnet = normalizeMagnet; exports.normalizeMultiColor = _chunkHRUK5TFWcjs.normalizeMultiColor; exports.normalizeMutation = _chunkHRUK5TFWcjs.normalizeMutation; exports.normalizeMutationRates = normalizeMutationRates; exports.normalizePaintBrush = _chunkHRUK5TFWcjs.normalizePaintBrush; exports.normalizePaper = _chunkPEQWARCPcjs.normalizePaper; exports.normalizeParticle = _chunkHRUK5TFWcjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunkHRUK5TFWcjs.normalizeStickerSettings; exports.normalizeStickerUpdate = normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeThermochromic = _chunkHRUK5TFWcjs.normalizeThermochromic; exports.normalizeUvLight = normalizeUvLight; exports.normalizeView = normalizeView; exports.normalizeViewTilt = normalizeViewTilt; exports.normalizeWetBrush = _chunkHRUK5TFWcjs.normalizeWetBrush; exports.normalizeWetParams = _chunkMITQGHN3cjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintAgentStrokePoints = paintAgentStrokePoints; exports.paintBrushPreviewRenderer = paintBrushPreviewRenderer; exports.paintContracts = paintContracts; exports.paintGradientMappingFor = _chunkIFWLZZCWcjs.paintGradientMappingFor; exports.paintHeatField = paintHeatField; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintProposalGhost = paintProposalGhost; exports.paintShortcutFor = paintShortcutFor; exports.paintSourceColor = _chunkIFWLZZCWcjs.paintSourceColor; exports.paintSourceCss = _chunkIFWLZZCWcjs.paintSourceCss; exports.paintToMultiColor = _chunkHRUK5TFWcjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = _chunkPEQWARCPcjs.paperPreset; exports.parseBrushLibrary = _chunkHRUK5TFWcjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkIFWLZZCWcjs.parsePaintSource; exports.patchBrushValue = _chunkJVFGK3DKcjs.patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = _chunkPEQWARCPcjs.penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.proposalGenomeStrokes = proposalGenomeStrokes; exports.quickStencil = quickStencil; exports.rand01 = _chunk3K6HWEXZcjs.rand01; exports.randSigned = _chunk3K6HWEXZcjs.randSigned; exports.readEffectStrokeMap = _chunkPEQWARCPcjs.readEffectStrokeMap; exports.readPaintEffectPaint = _chunkPEQWARCPcjs.readPaintEffectPaint; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkIFWLZZCWcjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkIFWLZZCWcjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = _chunkPEQWARCPcjs.renderPaper; exports.renderProposalContactSheet = renderProposalContactSheet; exports.renderStickers = renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.requestDeviceTiltPermission = requestDeviceTiltPermission; exports.rerollStrokeSeed = rerollStrokeSeed; exports.resampleStrokePoints = resampleStrokePoints; exports.resolvePaintGradient = _chunkIFWLZZCWcjs.resolvePaintGradient; exports.reversePaintGradient = _chunkIFWLZZCWcjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.sampleArt = sampleArt; exports.sampleEffectAt = _chunkPEQWARCPcjs.sampleEffectAt; exports.sampleEffectField = _chunkPEQWARCPcjs.sampleEffectField; exports.sampleHeatAt = sampleHeatAt; exports.samplePath = samplePath; exports.samplePressure = samplePressure; exports.scaleFerro = scaleFerro; exports.scaleFluor = scaleFluor; exports.scalePaintGradient = _chunkIFWLZZCWcjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunk3K6HWEXZcjs.seedFromString; exports.seededStrokeVariation = seededStrokeVariation; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.shadowToFerro = shadowToFerro; exports.shiftHeatField = shiftHeatField; exports.solidPaint = _chunkIFWLZZCWcjs.solidPaint; exports.squaredDistanceTransform = _chunkYH6SKC7Pcjs.squaredDistanceTransform; exports.stampCoverage = _chunkRDFHWAHLcjs.stampCoverage; exports.standardBlendMode = _chunk2VX55NFMcjs.standardBlendMode; exports.startDeviceTilt = startDeviceTilt; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerAt = stickerAt; exports.stickerRect = stickerRect; exports.stickerRefLabel = stickerRefLabel; exports.stickerStamp = stickerStamp; exports.stickerSurface = stickerSurface; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokePathPoints = _chunkPEQWARCPcjs.strokePathPoints; exports.strokeSchedule = strokeSchedule; exports.strokeToJSON = strokeToJSON; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thermoFromJSON = thermoFromJSON; exports.thermoToJSON = thermoToJSON; exports.thermoTwinBrush = thermoTwinBrush; exports.thickFromJSON = thickFromJSON; exports.thickToJSON = thickToJSON; exports.thinFilmRgb = thinFilmRgb; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = _chunkPEQWARCPcjs.tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = _chunkPEQWARCPcjs.toStrokePoint; exports.toggleDotTexture = toggleDotTexture; exports.toggleStamp = toggleStamp; exports.toggleStickerRef = toggleStickerRef; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkIFWLZZCWcjs.updatePaintGradientStop; exports.usesPaintExchange = _chunkHRUK5TFWcjs.usesPaintExchange; exports.uvLightKey = uvLightKey; exports.uvPaper = uvPaper; exports.variationAffine = variationAffine; exports.varyStroke = varyStroke; exports.viewCssTransform = viewCssTransform; exports.viewMatrix = viewMatrix; exports.viewPenToDocument = viewPenToDocument; exports.viewTiltKey = viewTiltKey; exports.wetEngineSummary = wetEngineSummary; exports.wetPaperInput = _chunkPEQWARCPcjs.wetPaperInput; exports.wetPigmentOf = _chunkPEQWARCPcjs.wetPigmentOf; exports.wetSupport = _chunkMITQGHN3cjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunkI3Y2Q3PMcjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback; exports.withStrokePath = _chunkPEQWARCPcjs.withStrokePath;
18237
+
18238
+ exports.BACKLIGHT_SPILL = BACKLIGHT_SPILL; exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunk2VX55NFMcjs.BLEND_MODES; exports.BRUSH_ID = _chunkHRUK5TFWcjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunkHRUK5TFWcjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = _chunkJVFGK3DKcjs.BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunkHRUK5TFWcjs.BUILTIN_BRUSHES; exports.BristleStroke = BristleStroke; exports.BrushSourceArtCache = BrushSourceArtCache; exports.DAB_FLIPS = _chunkHRUK5TFWcjs.DAB_FLIPS; exports.DEFAULT_BACKLIGHT_COLOR = DEFAULT_BACKLIGHT_COLOR; exports.DEFAULT_BEHAVIOR = _chunkHRUK5TFWcjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunkHRUK5TFWcjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunkHRUK5TFWcjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunkHRUK5TFWcjs.DEFAULT_DYNAMICS; exports.DEFAULT_FERRO = _chunkHRUK5TFWcjs.DEFAULT_FERRO; exports.DEFAULT_FLOW = _chunkMITQGHN3cjs.DEFAULT_FLOW; exports.DEFAULT_FLUORESCENCE = _chunkHRUK5TFWcjs.DEFAULT_FLUORESCENCE; exports.DEFAULT_GHOST = _chunkHRUK5TFWcjs.DEFAULT_GHOST; exports.DEFAULT_IMPASTO = _chunkHRUK5TFWcjs.DEFAULT_IMPASTO; exports.DEFAULT_IRIDESCENCE = _chunkHRUK5TFWcjs.DEFAULT_IRIDESCENCE; exports.DEFAULT_LIGHT = _chunkHRUK5TFWcjs.DEFAULT_LIGHT; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_LIVE_PATTERNS = _chunkIFWLZZCWcjs.DEFAULT_LIVE_PATTERNS; exports.DEFAULT_MAGNET_RADIUS = DEFAULT_MAGNET_RADIUS; exports.DEFAULT_MAGNET_STRENGTH = DEFAULT_MAGNET_STRENGTH; exports.DEFAULT_MULTI_COLOR = _chunkHRUK5TFWcjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_MUTATION = _chunkHRUK5TFWcjs.DEFAULT_MUTATION; exports.DEFAULT_MUTATION_RATES = DEFAULT_MUTATION_RATES; exports.DEFAULT_PAINT_GRADIENT = _chunkIFWLZZCWcjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkIFWLZZCWcjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = _chunkPEQWARCPcjs.DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunkHRUK5TFWcjs.DEFAULT_PARTICLE; exports.DEFAULT_SPRAY = _chunkHRUK5TFWcjs.DEFAULT_SPRAY; exports.DEFAULT_STICKER = _chunkHRUK5TFWcjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_THERMOCHROMIC = _chunkHRUK5TFWcjs.DEFAULT_THERMOCHROMIC; exports.DEFAULT_TIP_GRAIN = _chunkHRUK5TFWcjs.DEFAULT_TIP_GRAIN; exports.DEFAULT_UV_LIGHT = DEFAULT_UV_LIGHT; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_VIEW_TILT = DEFAULT_VIEW_TILT; exports.DEFAULT_WET_BRUSH = _chunkHRUK5TFWcjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkMITQGHN3cjs.DEFAULT_WET_PARAMS; exports.DOT_ROTATIONS = _chunkHRUK5TFWcjs.DOT_ROTATIONS; exports.DOT_ROTATION_LABELS = DOT_ROTATION_LABELS; exports.DOT_TEXTURE_ORDERS = _chunkHRUK5TFWcjs.DOT_TEXTURE_ORDERS; exports.DOT_TEXTURE_ORDER_LABELS = DOT_TEXTURE_ORDER_LABELS; exports.DryStroke = _chunkPEQWARCPcjs.DryStroke; exports.EFFECT_MAP_REPEATS = _chunkPEQWARCPcjs.EFFECT_MAP_REPEATS; exports.EFFECT_STRIP_HEIGHT = _chunkPEQWARCPcjs.EFFECT_STRIP_HEIGHT; exports.EVOLUTION_BRUSH_FACETS = EVOLUTION_BRUSH_FACETS; exports.EVOLUTION_MUTATION_SCHEMA = EVOLUTION_MUTATION_SCHEMA; exports.EVOLUTION_SLIDERS = EVOLUTION_SLIDERS; exports.EXTENSION_ASSET_REF = EXTENSION_ASSET_REF; exports.FERRO_CARRIER_RGB = FERRO_CARRIER_RGB; exports.FERRO_DEFAULT_GLOSS = FERRO_DEFAULT_GLOSS; exports.FERRO_DEFAULT_METALLIC = FERRO_DEFAULT_METALLIC; exports.FERRO_DEFAULT_RIM = FERRO_DEFAULT_RIM; exports.FilmBuffer = FilmBuffer; exports.GHOST_SLIDERS = _chunkJVFGK3DKcjs.GHOST_SLIDERS; exports.GHOST_TRIGGERS = _chunkHRUK5TFWcjs.GHOST_TRIGGERS; exports.GPU_LEAD = _chunkPEQWARCPcjs.GPU_LEAD; exports.GRAIN_PATTERNS = _chunkIFWLZZCWcjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkIFWLZZCWcjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunkI3Y2Q3PMcjs.HARMONY_KINDS; exports.HEAT_COOLING = HEAT_COOLING; exports.HEAT_DIFFUSION = HEAT_DIFFUSION; exports.HEAT_DRY_THRESHOLD = HEAT_DRY_THRESHOLD; exports.HEAT_SCALE = HEAT_SCALE; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = _chunkPEQWARCPcjs.IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunkHRUK5TFWcjs.IMPASTO_TOOLS; exports.IMPASTO_TOOL_LABELS = IMPASTO_TOOL_LABELS; exports.IRIDESCENCE_SLIDERS = _chunkJVFGK3DKcjs.IRIDESCENCE_SLIDERS; exports.LIGHT_SLIDERS = LIGHT_SLIDERS; exports.LIVE_PATTERN_KINDS = _chunkIFWLZZCWcjs.LIVE_PATTERN_KINDS; exports.LIVE_PATTERN_LABELS = LIVE_PATTERN_LABELS; exports.LIVE_PATTERN_PRESETS = _chunkIFWLZZCWcjs.LIVE_PATTERN_PRESETS; exports.LIVE_PATTERN_SCHEMA = LIVE_PATTERN_SCHEMA; exports.LIVE_PATTERN_SLIDERS = LIVE_PATTERN_SLIDERS; exports.LIVE_STROKE_ENGINES = LIVE_STROKE_ENGINES; exports.LitCache = LitCache; exports.MAGNET_SLIDERS = MAGNET_SLIDERS; exports.MAX_BRUSH_SIZE = _chunkIFWLZZCWcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_DOT_TEXTURES = _chunkHRUK5TFWcjs.MAX_DOT_TEXTURES; exports.MAX_EFFECT_PATH_POINTS = _chunkPEQWARCPcjs.MAX_EFFECT_PATH_POINTS; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_LIVE_EFFECT_SOURCES = MAX_LIVE_EFFECT_SOURCES; exports.MAX_PATH_SAMPLES = MAX_PATH_SAMPLES; exports.MAX_STICKER_STAMPS = _chunkHRUK5TFWcjs.MAX_STICKER_STAMPS; exports.MAX_ZOOM = MAX_ZOOM; exports.MIN_CANVAS_SIDE = MIN_CANVAS_SIDE; exports.MIN_ZOOM = MIN_ZOOM; exports.MIXING_PAD_HEIGHT = MIXING_PAD_HEIGHT; exports.MIXING_PAD_WIDTH = MIXING_PAD_WIDTH; exports.MULTI_COLOR_MODES = _chunkHRUK5TFWcjs.MULTI_COLOR_MODES; exports.MUTATION_SLIDERS = _chunkJVFGK3DKcjs.MUTATION_SLIDERS; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunk2VX55NFMcjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunkHRUK5TFWcjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunkHRUK5TFWcjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkIFWLZZCWcjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_CONTRACT_FORMAT_VERSION = PAINT_CONTRACT_FORMAT_VERSION; exports.PAINT_DOCUMENT_JSON_SCHEMA = PAINT_DOCUMENT_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkIFWLZZCWcjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkIFWLZZCWcjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkIFWLZZCWcjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkIFWLZZCWcjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkIFWLZZCWcjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SHORTCUTS = PAINT_SHORTCUTS; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkIFWLZZCWcjs.PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_TARGET = PAINT_TARGET; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_EFFECT_BLENDS = PAPER_EFFECT_BLENDS; exports.PAPER_EFFECT_NODE_ID = PAPER_EFFECT_NODE_ID; exports.PAPER_FAMILIES = _chunkPEQWARCPcjs.PAPER_FAMILIES; exports.PAPER_LIBRARY = _chunkPEQWARCPcjs.PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunkHRUK5TFWcjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunkHRUK5TFWcjs.PARTICLE_RENDERS; exports.PARTICLE_RENDER_LABELS = PARTICLE_RENDER_LABELS; exports.PATH_STROKE_TAPERS = PATH_STROKE_TAPERS; exports.PaintCanvasPresenter = PaintCanvasPresenter; exports.PaintDabStroke = _chunkPEQWARCPcjs.PaintDabStroke; exports.PaintDirector = PaintDirector; exports.PaintDocumentError = PaintDocumentError; exports.PaintEditorController = PaintEditorController; exports.PaintEditorError = PaintEditorError; exports.PaintEffectsRenderer = PaintEffectsRenderer; exports.PaintGesture = PaintGesture; exports.PaintGradientSampler = _chunkIFWLZZCWcjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkIFWLZZCWcjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = _chunkPEQWARCPcjs.PaintWetLayers; exports.PaperGrain = _chunkIFWLZZCWcjs.PaperGrain; exports.ParticleStroke = ParticleStroke; exports.PenDabWalker = _chunkPEQWARCPcjs.PenDabWalker; exports.PenSmoother = _chunkPEQWARCPcjs.PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.RIBBON_PAIRS = _chunkHRUK5TFWcjs.RIBBON_PAIRS; exports.RIBBON_PAIR_LABELS = RIBBON_PAIR_LABELS; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunkRDFHWAHLcjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_ART_SIZE = STICKER_ART_SIZE; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.STROKE_SLIDERS = STROKE_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerArtCache = StickerArtCache; exports.StickerBrowser = _chunk3VHH6V67cjs.StickerBrowser; exports.StickerSpray = StickerSpray; exports.TIP_GRAIN_MODES = _chunkHRUK5TFWcjs.TIP_GRAIN_MODES; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThermoCache = ThermoCache; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunk3K6HWEXZcjs.TileableNoise; exports.TipGrain = _chunkPEQWARCPcjs.TipGrain; exports.UV_LIGHT_SLIDERS = UV_LIGHT_SLIDERS; exports.UvCache = UvCache; exports.VIEW_TILT_SLIDERS = VIEW_TILT_SLIDERS; exports.WET_FLOW_KINDS = _chunkMITQGHN3cjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = _chunkPEQWARCPcjs.WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunkHRUK5TFWcjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = _chunkPEQWARCPcjs.WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkMITQGHN3cjs.WET_PARAM_KEYS; exports.WET_PARAM_SCHEMA = WET_PARAM_SCHEMA; exports.WET_PARAM_SLIDERS = WET_PARAM_SLIDERS; exports.WET_SPEED_SLIDER = WET_SPEED_SLIDER; exports.WET_TILT_SLIDERS = WET_TILT_SLIDERS; exports.WET_TOOLS = _chunkHRUK5TFWcjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = _chunkPEQWARCPcjs.WetStrokeDriver; exports.addPaintGradientStop = _chunkIFWLZZCWcjs.addPaintGradientStop; exports.addPolygonArea = addPolygonArea; exports.advanceHeatField = advanceHeatField; exports.advectFerro = advectFerro; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.backlightOf = backlightOf; exports.bakeFerroIntoThick = bakeFerroIntoThick; exports.brushEngineControls = _chunkJVFGK3DKcjs.brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunkHRUK5TFWcjs.brushTakesPaint; exports.brushToJSON = _chunkHRUK5TFWcjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkEvolutionStrokes = checkEvolutionStrokes; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clearHeatField = clearHeatField; exports.cloneHeatField = cloneHeatField; exports.clonePaper = _chunkPEQWARCPcjs.clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.computeUvSpill = computeUvSpill; exports.contactSheet = contactSheet; exports.createEvolutionTools = createEvolutionTools; exports.createFerroTools = createFerroTools; exports.createHeatField = createHeatField; exports.createMutationTools = createMutationTools; exports.createPaintAgentStrokes = createPaintAgentStrokes; exports.createPaintBrushLibraryToolProvider = createPaintBrushLibraryToolProvider; exports.createPaintChangeFeed = createPaintChangeFeed; exports.createPaintCompositor = createPaintCompositor; exports.createPaintConformanceHost = createPaintConformanceHost; exports.createPaintDocument = createPaintDocument; exports.createPaintEditorDocument = createPaintEditorDocument; exports.createPaintEditorToolProvider = createPaintEditorToolProvider; exports.createPaintEffectsToolProvider = createPaintEffectsToolProvider; exports.createPaintEvolutionToolProvider = createPaintEvolutionToolProvider; exports.createPaintEvolutionTools = createPaintEvolutionTools; exports.createPaintLayer = createPaintLayer; exports.createPaintProposalToolProvider = createPaintProposalToolProvider; exports.createPaintProposals = createPaintProposals; exports.createPaintReplayTools = createPaintReplayTools; exports.createPaintStickerTools = createPaintStickerTools; exports.createPaintThickTools = createPaintThickTools; exports.createPaintWetTools = createPaintWetTools; exports.crossoverBrushes = crossoverBrushes; exports.crossoverGenomes = crossoverGenomes; exports.crossoverStrokes = crossoverStrokes; exports.decodeImageBlob = decodeImageBlob; exports.defaultGuides = defaultGuides; exports.defaultImageEncoder = defaultImageEncoder; exports.defaultStickerRasterizer = defaultStickerRasterizer; exports.describeGenomeDiff = describeGenomeDiff; exports.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.deviceOrientationToViewTilt = deviceOrientationToViewTilt; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.drawSticker = drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.driftBrushFacets = driftBrushFacets; exports.driftColorOklch = driftColorOklch; exports.effectDabField = _chunkPEQWARCPcjs.effectDabField; exports.effectLayersToJSON = effectLayersToJSON; exports.effectPaintKey = _chunkPEQWARCPcjs.effectPaintKey; exports.effectPaintSize = _chunkPEQWARCPcjs.effectPaintSize; exports.emptiedLayers = emptiedLayers; exports.emptyFerro = emptyFerro; exports.emptyFluor = emptyFluor; exports.emptyThermo = emptyThermo; exports.emptyThickChannels = emptyThickChannels; exports.engineBrushSourceIds = engineBrushSourceIds; exports.exportProposalContactSheetPng = exportProposalContactSheetPng; exports.ferroCacheKey = ferroCacheKey; exports.ferroFieldAt = ferroFieldAt; exports.ferroFromJSON = ferroFromJSON; exports.ferroInfo = ferroInfo; exports.ferroSpikeHeightAt = ferroSpikeHeightAt; exports.ferroToJSON = ferroToJSON; exports.ferroToShadow = ferroToShadow; exports.ferroTwinBrush = ferroTwinBrush; exports.fillRegionMask = _chunkYH6SKC7Pcjs.fillRegionMask; exports.finalizeThermoStroke = finalizeThermoStroke; exports.findUnfilledRegionsMask = _chunkYH6SKC7Pcjs.findUnfilledRegionsMask; exports.fitZoom = fitZoom; exports.fluorFromJSON = fluorFromJSON; exports.fluorToJSON = fluorToJSON; exports.fluorTwinBrush = fluorTwinBrush; exports.grainCatch = _chunkIFWLZZCWcjs.grainCatch; exports.grainHeights = _chunkIFWLZZCWcjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hasThickChannels = hasThickChannels; exports.hash2 = _chunk3K6HWEXZcjs.hash2; exports.heatFromJSON = heatFromJSON; exports.heatStats = heatStats; exports.heatToJSON = heatToJSON; exports.hexToPaintRgb = _chunkIFWLZZCWcjs.hexToPaintRgb; exports.hexToRgb8 = _chunkPEQWARCPcjs.hexToRgb8; exports.hotCellsBounds = hotCellsBounds; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunkI3Y2Q3PMcjs.hueToWheel; exports.inferEffectPathControl = _chunkPEQWARCPcjs.inferEffectPathControl; exports.invertAffine = invertAffine; exports.isBlendMode = _chunk2VX55NFMcjs.isBlendMode; exports.isGradientPaint = _chunkIFWLZZCWcjs.isGradientPaint; exports.isPaintEffectPaint = _chunkPEQWARCPcjs.isPaintEffectPaint; exports.isPainterlyBlendMode = _chunk2VX55NFMcjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunkHRUK5TFWcjs.isWetBrush; exports.isWetCapable = _chunkHRUK5TFWcjs.isWetCapable; exports.jitterStrokePoints = jitterStrokePoints; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.liveStrokeBounds = liveStrokeBounds; exports.liveStrokeRefusal = liveStrokeRefusal; exports.magnetsFromJSON = magnetsFromJSON; exports.mapPenPoint = mapPenPoint; exports.mergeFerro = mergeFerro; exports.mergeFourChannel = mergeFourChannel; exports.mix32 = _chunk3K6HWEXZcjs.mix32; exports.mixColorOklch = mixColorOklch; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = _chunkPEQWARCPcjs.mixerTip; exports.multiColorForDab = _chunkPEQWARCPcjs.multiColorForDab; exports.multiColorGradient = _chunkPEQWARCPcjs.multiColorGradient; exports.multiColorPalette = _chunkPEQWARCPcjs.multiColorPalette; exports.multiColorSliders = _chunkJVFGK3DKcjs.multiColorSliders; exports.multiColorToPaint = _chunkHRUK5TFWcjs.multiColorToPaint; exports.mutateGenome = mutateGenome; exports.mutateStroke = mutateStroke; exports.mutationBrushRefusal = mutationBrushRefusal; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunkHRUK5TFWcjs.normalizeBehavior; exports.normalizeBristle = _chunkHRUK5TFWcjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunkHRUK5TFWcjs.normalizeDynamics; exports.normalizeFerro = _chunkHRUK5TFWcjs.normalizeFerro; exports.normalizeFerroSettings = _chunkHRUK5TFWcjs.normalizeFerro; exports.normalizeFlow = _chunkMITQGHN3cjs.normalizeFlow; exports.normalizeFluorescence = _chunkHRUK5TFWcjs.normalizeFluorescence; exports.normalizeGhost = _chunkHRUK5TFWcjs.normalizeGhost; exports.normalizeHexColor = _chunkIFWLZZCWcjs.normalizeHexColor; exports.normalizeImpasto = _chunkHRUK5TFWcjs.normalizeImpasto; exports.normalizeLight = _chunkHRUK5TFWcjs.normalizeLight; exports.normalizeLighting = normalizeLighting; exports.normalizeLivePatterns = _chunkIFWLZZCWcjs.normalizeLivePatterns; exports.normalizeMagnet = normalizeMagnet; exports.normalizeMultiColor = _chunkHRUK5TFWcjs.normalizeMultiColor; exports.normalizeMutation = _chunkHRUK5TFWcjs.normalizeMutation; exports.normalizeMutationRates = normalizeMutationRates; exports.normalizePaintBrush = _chunkHRUK5TFWcjs.normalizePaintBrush; exports.normalizePaper = _chunkPEQWARCPcjs.normalizePaper; exports.normalizeParticle = _chunkHRUK5TFWcjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunkHRUK5TFWcjs.normalizeStickerSettings; exports.normalizeStickerUpdate = normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeThermochromic = _chunkHRUK5TFWcjs.normalizeThermochromic; exports.normalizeUvLight = normalizeUvLight; exports.normalizeView = normalizeView; exports.normalizeViewTilt = normalizeViewTilt; exports.normalizeWetBrush = _chunkHRUK5TFWcjs.normalizeWetBrush; exports.normalizeWetParams = _chunkMITQGHN3cjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintAgentStrokePoints = paintAgentStrokePoints; exports.paintBrushPreviewRenderer = paintBrushPreviewRenderer; exports.paintContracts = paintContracts; exports.paintGradientMappingFor = _chunkIFWLZZCWcjs.paintGradientMappingFor; exports.paintHeatField = paintHeatField; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintProposalGhost = paintProposalGhost; exports.paintShortcutFor = paintShortcutFor; exports.paintSourceColor = _chunkIFWLZZCWcjs.paintSourceColor; exports.paintSourceCss = _chunkIFWLZZCWcjs.paintSourceCss; exports.paintToMultiColor = _chunkHRUK5TFWcjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = _chunkPEQWARCPcjs.paperPreset; exports.parseBrushLibrary = _chunkHRUK5TFWcjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkIFWLZZCWcjs.parsePaintSource; exports.patchBrushValue = _chunkJVFGK3DKcjs.patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = _chunkPEQWARCPcjs.penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.proposalGenomeStrokes = proposalGenomeStrokes; exports.quickStencil = quickStencil; exports.rand01 = _chunk3K6HWEXZcjs.rand01; exports.randSigned = _chunk3K6HWEXZcjs.randSigned; exports.readEffectStrokeMap = _chunkPEQWARCPcjs.readEffectStrokeMap; exports.readPaintEffectPaint = _chunkPEQWARCPcjs.readPaintEffectPaint; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkIFWLZZCWcjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkIFWLZZCWcjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = _chunkPEQWARCPcjs.renderPaper; exports.renderProposalContactSheet = renderProposalContactSheet; exports.renderStickers = renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.requestDeviceTiltPermission = requestDeviceTiltPermission; exports.rerollStrokeSeed = rerollStrokeSeed; exports.resampleStrokePoints = resampleStrokePoints; exports.resolvePaintGradient = _chunkIFWLZZCWcjs.resolvePaintGradient; exports.reversePaintGradient = _chunkIFWLZZCWcjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.sampleArt = sampleArt; exports.sampleEffectAt = _chunkPEQWARCPcjs.sampleEffectAt; exports.sampleEffectField = _chunkPEQWARCPcjs.sampleEffectField; exports.sampleHeatAt = sampleHeatAt; exports.samplePath = samplePath; exports.samplePressure = samplePressure; exports.scaleFerro = scaleFerro; exports.scaleFluor = scaleFluor; exports.scalePaintGradient = _chunkIFWLZZCWcjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunk3K6HWEXZcjs.seedFromString; exports.seededStrokeVariation = seededStrokeVariation; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.shadowToFerro = shadowToFerro; exports.shiftHeatField = shiftHeatField; exports.solidPaint = _chunkIFWLZZCWcjs.solidPaint; exports.squaredDistanceTransform = _chunkYH6SKC7Pcjs.squaredDistanceTransform; exports.stampCoverage = _chunkRDFHWAHLcjs.stampCoverage; exports.standardBlendMode = _chunk2VX55NFMcjs.standardBlendMode; exports.startDeviceTilt = startDeviceTilt; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerAt = stickerAt; exports.stickerRect = stickerRect; exports.stickerRefLabel = stickerRefLabel; exports.stickerStamp = stickerStamp; exports.stickerSurface = stickerSurface; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokePathPoints = _chunkPEQWARCPcjs.strokePathPoints; exports.strokeSchedule = strokeSchedule; exports.strokeToJSON = strokeToJSON; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thermoFromJSON = thermoFromJSON; exports.thermoToJSON = thermoToJSON; exports.thermoTwinBrush = thermoTwinBrush; exports.thickFromJSON = thickFromJSON; exports.thickToJSON = thickToJSON; exports.thinFilmRgb = thinFilmRgb; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = _chunkPEQWARCPcjs.tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = _chunkPEQWARCPcjs.toStrokePoint; exports.toggleDotTexture = toggleDotTexture; exports.toggleStamp = toggleStamp; exports.toggleStickerRef = toggleStickerRef; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkIFWLZZCWcjs.updatePaintGradientStop; exports.usesPaintExchange = _chunkHRUK5TFWcjs.usesPaintExchange; exports.uvLightKey = uvLightKey; exports.uvPaper = uvPaper; exports.variationAffine = variationAffine; exports.varyStroke = varyStroke; exports.viewCssTransform = viewCssTransform; exports.viewMatrix = viewMatrix; exports.viewPenToDocument = viewPenToDocument; exports.viewTiltKey = viewTiltKey; exports.wetEngineSummary = wetEngineSummary; exports.wetPaperInput = _chunkPEQWARCPcjs.wetPaperInput; exports.wetPigmentOf = _chunkPEQWARCPcjs.wetPigmentOf; exports.wetSupport = _chunkMITQGHN3cjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunkI3Y2Q3PMcjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback; exports.withStrokePath = _chunkPEQWARCPcjs.withStrokePath;