@pixerate/editor 0.273.0 → 0.275.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation-editor/index.cjs +60 -60
- package/dist/animation-editor/index.js +4 -4
- package/dist/brushes/index.cjs +102 -74
- package/dist/brushes/index.js +34 -6
- package/dist/brushes/patch.d.cts +1 -1
- package/dist/brushes/patch.d.ts +1 -1
- package/dist/brushes/preview.d.cts +3 -0
- package/dist/brushes/preview.d.ts +3 -0
- package/dist/brushes/profiles.d.cts +2 -0
- package/dist/brushes/profiles.d.ts +2 -0
- package/dist/brushes/schema.d.cts +4 -0
- package/dist/brushes/schema.d.ts +4 -0
- package/dist/brushes/types.d.cts +47 -0
- package/dist/brushes/types.d.ts +47 -0
- package/dist/{brushstrokeRender-5YBCLFDQ.cjs → brushstrokeRender-2RQL46WB.cjs} +15 -15
- package/dist/{brushstrokeRender-DZGFU3J4.js → brushstrokeRender-WGY4DZHF.js} +3 -3
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-2XDNF73E.js → chunk-43XJC3PP.js} +1 -1
- package/dist/{chunk-GHGBIAWQ.cjs → chunk-6QNDGMK7.cjs} +263 -45
- package/dist/{chunk-2F3YDXCN.js → chunk-75SYKUOT.js} +1 -1
- package/dist/{chunk-M3RZOF3G.cjs → chunk-C6VB7CPY.cjs} +1 -1
- package/dist/{chunk-N5IMDAHM.cjs → chunk-DHC4E2DU.cjs} +89 -37
- package/dist/{chunk-NAHJV3O6.js → chunk-G5TCMKX5.js} +28 -11
- package/dist/{chunk-DZVRH63Y.js → chunk-IEEY5RJV.js} +1 -1
- package/dist/{chunk-7W2EQQBP.cjs → chunk-JDXWLCXF.cjs} +6 -6
- package/dist/{chunk-N3SKPQEH.js → chunk-LMG57L5A.js} +62 -10
- package/dist/{chunk-5HP2VSAS.js → chunk-MSWLJI4G.js} +1 -1
- package/dist/{chunk-SNAFFCAX.cjs → chunk-OLZXXAER.cjs} +221 -196
- package/dist/{chunk-YJANF2BL.cjs → chunk-RAPNRK4R.cjs} +86 -86
- package/dist/{chunk-CLB2I2FU.js → chunk-RJGW3RQS.js} +2 -2
- package/dist/{chunk-FXVCB6YG.cjs → chunk-T6KNJVBP.cjs} +35 -35
- package/dist/{chunk-ZEI7ZEA4.js → chunk-Y2ISSVPH.js} +34 -9
- package/dist/{chunk-3JKCREEU.cjs → chunk-Y354ETAE.cjs} +76 -59
- package/dist/{chunk-TNLKFW7D.cjs → chunk-YYZC2EQO.cjs} +23 -23
- package/dist/{chunk-UXYCY3HP.js → chunk-ZM7IKQ4X.js} +239 -21
- package/dist/image-editor/index.cjs +789 -789
- package/dist/image-editor/index.js +5 -5
- package/dist/paint/index.cjs +2 -2
- package/dist/paint/index.js +1 -1
- package/dist/paint/wet/world.d.cts +15 -2
- package/dist/paint/wet/world.d.ts +15 -2
- package/dist/paint-editor/brush-controls.d.cts +7 -0
- package/dist/paint-editor/brush-controls.d.ts +7 -0
- package/dist/paint-editor/brush-model.d.cts +59 -1
- package/dist/paint-editor/brush-model.d.ts +59 -1
- package/dist/paint-editor/collaboration.d.cts +6 -1
- package/dist/paint-editor/collaboration.d.ts +6 -1
- package/dist/paint-editor/controller.d.cts +199 -1
- package/dist/paint-editor/controller.d.ts +199 -1
- package/dist/paint-editor/dab-stroke.d.cts +3 -0
- package/dist/paint-editor/dab-stroke.d.ts +3 -0
- package/dist/paint-editor/document.d.cts +13 -3
- package/dist/paint-editor/document.d.ts +13 -3
- package/dist/paint-editor/engine.d.cts +3 -0
- package/dist/paint-editor/engine.d.ts +3 -0
- package/dist/paint-editor/evolution-tools.d.cts +48 -0
- package/dist/paint-editor/evolution-tools.d.ts +48 -0
- package/dist/paint-editor/evolution.d.cts +175 -0
- package/dist/paint-editor/evolution.d.ts +175 -0
- package/dist/paint-editor/heat.d.cts +156 -0
- package/dist/paint-editor/heat.d.ts +156 -0
- package/dist/paint-editor/index.cjs +4905 -1525
- package/dist/paint-editor/index.d.cts +5 -0
- package/dist/paint-editor/index.d.ts +5 -0
- package/dist/paint-editor/index.js +10952 -7572
- package/dist/paint-editor/mutation-tools.d.cts +13 -0
- package/dist/paint-editor/mutation-tools.d.ts +13 -0
- package/dist/paint-editor/mutation.d.cts +67 -0
- package/dist/paint-editor/mutation.d.ts +67 -0
- package/dist/paint-editor/presence.d.cts +7 -1
- package/dist/paint-editor/presence.d.ts +7 -1
- package/dist/paint-editor/procedural.d.cts +3 -0
- package/dist/paint-editor/procedural.d.ts +3 -0
- package/dist/paint-editor/stroke.d.cts +32 -2
- package/dist/paint-editor/stroke.d.ts +32 -2
- package/dist/paint-editor/thick.d.cts +48 -7
- package/dist/paint-editor/thick.d.ts +48 -7
- package/dist/paint-editor/ui.d.cts +36 -1
- package/dist/paint-editor/ui.d.ts +36 -1
- package/dist/paint-editor/wet.d.cts +8 -1
- package/dist/paint-editor/wet.d.ts +8 -1
- package/dist/vector/index.cjs +999 -999
- package/dist/vector/index.js +5 -5
- package/package.json +1 -1
- package/skills/README.md +1 -0
- package/skills/pixerate-brushes/SKILL.md +3 -0
- package/skills/pixerate-paint-editor/SKILL.md +36 -53
- package/skills/pixerate-paint-editor/references/brush-facets.md +3 -0
- package/skills/pixerate-paint-editor/references/mutation.md +25 -0
- package/skills/pixerate-paint-editor/references/oils.md +8 -1
- package/skills/pixerate-paint-editor/references/smart-inks.md +51 -0
- package/skills/pixerate-paint-mutation/SKILL.md +76 -0
- package/skills/pixerate-paint-mutation/evals/decline-unanswered.json +58 -0
- package/skills/pixerate-paint-mutation/evals/dry-ink-answer.json +74 -0
- package/skills/pixerate-paint-mutation/evals/wet-wash-answer.json +76 -0
- package/skills/pixerate-paint-oil-impasto/SKILL.md +2 -1
|
@@ -850,7 +850,7 @@ var S2 = SLOT_SIDE;
|
|
|
850
850
|
var SNAP_PLANES = SET_PLANES + MASS_CHANNELS;
|
|
851
851
|
var noLight = () => new (0, _chunk474IQG74cjs.TiledSurface)(1, /* @__PURE__ */ new Map(), 0);
|
|
852
852
|
function cloneGhost(g) {
|
|
853
|
-
return g ? { pigment: [...g.pigment], remaining: g.remaining, total: g.total, linger: g.linger } : null;
|
|
853
|
+
return g ? { pigment: [...g.pigment], remaining: g.remaining, total: g.total, linger: g.linger, ...g.trigger === "agent" ? { trigger: "agent" } : {} } : null;
|
|
854
854
|
}
|
|
855
855
|
function newLane(id, index, params, flow, flowStrength, base, light, ghost) {
|
|
856
856
|
const l = _nullishCoalesce(light, () => ( noLight()));
|
|
@@ -1119,21 +1119,59 @@ var WetWorld = (_class = class {
|
|
|
1119
1119
|
}
|
|
1120
1120
|
/**
|
|
1121
1121
|
* Starts a ghost paint fade on `id` with `pigment` per unit tracer and `linger` seconds. If an
|
|
1122
|
-
* earlier ghost of a different colour is still fading on the layer, it finishes at once first
|
|
1122
|
+
* earlier ghost of a different colour is still fading on the layer, it finishes at once first
|
|
1123
|
+
* (or keeps its paint when it was an unclaimed agent-triggered ghost).
|
|
1123
1124
|
*/
|
|
1124
|
-
startGhost(id, pigment, linger, stepsPerSecond = 120) {
|
|
1125
|
+
startGhost(id, pigment, linger, stepsPerSecond = 120, trigger = "immediate") {
|
|
1125
1126
|
this.requireIdle();
|
|
1126
1127
|
const lane = this.laneOf(id);
|
|
1127
1128
|
const p = [Math.fround(pigment[0]), Math.fround(pigment[1]), Math.fround(pigment[2]), Math.fround(pigment[3])];
|
|
1128
1129
|
if (lane.ghost) {
|
|
1129
1130
|
const g = lane.ghost.pigment;
|
|
1130
1131
|
const same = Math.abs(g[0] - p[0]) <= 1e-6 && Math.abs(g[1] - p[1]) <= 1e-6 && Math.abs(g[2] - p[2]) <= 1e-6 && Math.abs(g[3] - p[3]) <= 1e-6;
|
|
1131
|
-
if (!same)
|
|
1132
|
+
if (!same) {
|
|
1133
|
+
if (lane.ghost.trigger === "agent") this.keepGhost(id);
|
|
1134
|
+
else this.fadeGhost(id, 1);
|
|
1135
|
+
}
|
|
1132
1136
|
}
|
|
1133
1137
|
const total = Math.max(1, Math.round(linger * stepsPerSecond / FREE_INTERVAL));
|
|
1134
|
-
lane.ghost = { pigment: p, remaining: total, total, linger };
|
|
1138
|
+
lane.ghost = { pigment: p, remaining: total, total, linger, ...trigger === "agent" ? { trigger: "agent" } : {} };
|
|
1135
1139
|
lane.lit = false;
|
|
1136
1140
|
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Releases a held (`trigger: 'agent'`) ghost on `id` so its fade starts counting down on the
|
|
1143
|
+
* simulation clock over `linger` seconds (default: the lane's configured `linger`).
|
|
1144
|
+
*/
|
|
1145
|
+
releaseGhost(id, linger, stepsPerSecond = 120) {
|
|
1146
|
+
this.requireIdle();
|
|
1147
|
+
const lane = this.laneOf(id);
|
|
1148
|
+
if (!lane.ghost) return;
|
|
1149
|
+
const l = _nullishCoalesce(linger, () => ( lane.ghost.linger));
|
|
1150
|
+
const total = Math.max(1, Math.round(l * stepsPerSecond / FREE_INTERVAL));
|
|
1151
|
+
lane.ghost = { pigment: lane.ghost.pigment, remaining: total, total, linger: l };
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Drops a ghost lane's tracer (`P_L`, `P_DL`) without subtracting its pigment, so an unclaimed
|
|
1155
|
+
* or declined wet mutation stroke stays as ordinary wet paint.
|
|
1156
|
+
*/
|
|
1157
|
+
keepGhost(id) {
|
|
1158
|
+
this.requireIdle();
|
|
1159
|
+
const lane = this.laneOf(id);
|
|
1160
|
+
if (!lane.ghost) return;
|
|
1161
|
+
const f = this.f32;
|
|
1162
|
+
for (const key of this.active) {
|
|
1163
|
+
if (this.laneIndexOf(key) !== lane.index) continue;
|
|
1164
|
+
const slot = this.slotOf(key);
|
|
1165
|
+
if (slot < 0) continue;
|
|
1166
|
+
const b = this.slotBase(slot);
|
|
1167
|
+
const cur = b + this.parity * SET_PLANES * PLANE;
|
|
1168
|
+
f.fill(0, cur + P_L * PLANE, cur + (P_L + 1) * PLANE);
|
|
1169
|
+
f.fill(0, b + P_DL * PLANE, b + (P_DL + 1) * PLANE);
|
|
1170
|
+
this.gpuDirtySlot(slot, 1, WET_TILE);
|
|
1171
|
+
}
|
|
1172
|
+
lane.ghost = null;
|
|
1173
|
+
this.refreshHalos();
|
|
1174
|
+
}
|
|
1137
1175
|
pack(lane) {
|
|
1138
1176
|
packWetParams(lane.params, _nullishCoalesce(this.paper, () => ( DEFAULT_WET_PAPER)), this.tilt, lane.flowStrength, this.prm);
|
|
1139
1177
|
this.f32.set(this.prm, this.layout.params + lane.index * PARAM_FLOATS * 4 >> 2);
|
|
@@ -1367,7 +1405,7 @@ var WetWorld = (_class = class {
|
|
|
1367
1405
|
for (const key of wakeups) woke = this.activate(key) || woke;
|
|
1368
1406
|
if (this.clock % FREE_INTERVAL === 0) {
|
|
1369
1407
|
for (const lane of this.lanes) {
|
|
1370
|
-
if (!_optionalChain([lane, 'optionalAccess', _19 => _19.ghost])) continue;
|
|
1408
|
+
if (!_optionalChain([lane, 'optionalAccess', _19 => _19.ghost]) || lane.ghost.trigger === "agent") continue;
|
|
1371
1409
|
const g = lane.ghost;
|
|
1372
1410
|
const amount = g.remaining <= 1 ? 1 : 1 / g.remaining;
|
|
1373
1411
|
g.remaining = Math.max(0, g.remaining - 1);
|
|
@@ -1931,12 +1969,16 @@ var WetWorld = (_class = class {
|
|
|
1931
1969
|
continue;
|
|
1932
1970
|
}
|
|
1933
1971
|
const f = this.f32;
|
|
1934
|
-
const pig =
|
|
1972
|
+
const pig = lane.ghost && lane.ghost.trigger !== "agent" ? lane.ghost.pigment : null;
|
|
1973
|
+
const clearTracer = Boolean(lane.ghost && lane.ghost.trigger === "agent");
|
|
1935
1974
|
for (let y = y0; y < y1; y++) {
|
|
1936
1975
|
for (let x = x0; x < x1; x++) {
|
|
1937
1976
|
const c = this.cell(lane, x, y);
|
|
1938
1977
|
const d = this.single(c) + P_D0 * PLANE;
|
|
1939
|
-
if (
|
|
1978
|
+
if (clearTracer) {
|
|
1979
|
+
f[c + P_L * PLANE] = 0;
|
|
1980
|
+
f[d + 4 * PLANE] = 0;
|
|
1981
|
+
} else if (pig) {
|
|
1940
1982
|
const tl = f[c + P_L * PLANE];
|
|
1941
1983
|
const dl = f[d + 4 * PLANE];
|
|
1942
1984
|
if (tl > 0 || dl > 0) {
|
|
@@ -1980,7 +2022,17 @@ var WetWorld = (_class = class {
|
|
|
1980
2022
|
bakeKey(key, all) {
|
|
1981
2023
|
const lane = this.lanes[this.laneIndexOf(key)];
|
|
1982
2024
|
if (lane.ghost) {
|
|
1983
|
-
|
|
2025
|
+
if (lane.ghost.trigger === "agent") {
|
|
2026
|
+
const slot = this.slotOf(key);
|
|
2027
|
+
if (slot >= 0) {
|
|
2028
|
+
const b = this.slotBase(slot);
|
|
2029
|
+
const cur = b + this.parity * SET_PLANES * PLANE;
|
|
2030
|
+
this.f32.fill(0, cur + P_L * PLANE, cur + (P_L + 1) * PLANE);
|
|
2031
|
+
this.f32.fill(0, b + P_DL * PLANE, b + (P_DL + 1) * PLANE);
|
|
2032
|
+
}
|
|
2033
|
+
} else {
|
|
2034
|
+
this.fadeGhostKey(key, lane, 1);
|
|
2035
|
+
}
|
|
1984
2036
|
if (!this.hasGhostTracer(lane)) lane.ghost = null;
|
|
1985
2037
|
}
|
|
1986
2038
|
const [tx, ty] = this.tileXY(key);
|
|
@@ -1997,7 +2049,7 @@ var WetWorld = (_class = class {
|
|
|
1997
2049
|
lightChanged = true;
|
|
1998
2050
|
}
|
|
1999
2051
|
}
|
|
2000
|
-
const src = _nullishCoalesce(_optionalChain([lane, 'access',
|
|
2052
|
+
const src = _nullishCoalesce(_optionalChain([lane, 'access', _22 => _22.base, 'access', _23 => _23.tiles, 'access', _24 => _24.get, 'call', _25 => _25(tk), 'optionalAccess', _26 => _26.data]), () => ( null));
|
|
2001
2053
|
const out = this.shadeSlot(key, src, all ? "bake-all" : "bake");
|
|
2002
2054
|
if (!out) return lightChanged;
|
|
2003
2055
|
const tiles = new Map(lane.base.tiles);
|
|
@@ -2062,7 +2114,7 @@ var WetWorld = (_class = class {
|
|
|
2062
2114
|
if (this.laneIndexOf(key) !== lane.index) continue;
|
|
2063
2115
|
const tk = this.tileKeyOf(key);
|
|
2064
2116
|
let out;
|
|
2065
|
-
if (lane.ghost) {
|
|
2117
|
+
if (lane.ghost && lane.ghost.trigger !== "agent") {
|
|
2066
2118
|
const b = this.slotBase(this.slotOf(key));
|
|
2067
2119
|
const cur = b + this.parity * SET_PLANES * PLANE;
|
|
2068
2120
|
const savedP = this.f32.slice(cur + P_P0 * PLANE, cur + (P_P0 + MASS_CHANNELS) * PLANE);
|
|
@@ -2087,11 +2139,11 @@ var WetWorld = (_class = class {
|
|
|
2087
2139
|
}
|
|
2088
2140
|
}
|
|
2089
2141
|
}
|
|
2090
|
-
out = this.shadeSlot(key, _nullishCoalesce(_optionalChain([lane, 'access',
|
|
2142
|
+
out = this.shadeSlot(key, _nullishCoalesce(_optionalChain([lane, 'access', _27 => _27.base, 'access', _28 => _28.tiles, 'access', _29 => _29.get, 'call', _30 => _30(tk), 'optionalAccess', _31 => _31.data]), () => ( null)), "bake-all");
|
|
2091
2143
|
this.f32.set(savedP, cur + P_P0 * PLANE);
|
|
2092
2144
|
this.f32.set(savedD, b + P_D0 * PLANE);
|
|
2093
2145
|
} else {
|
|
2094
|
-
out = this.shadeSlot(key, _nullishCoalesce(_optionalChain([lane, 'access',
|
|
2146
|
+
out = this.shadeSlot(key, _nullishCoalesce(_optionalChain([lane, 'access', _32 => _32.base, 'access', _33 => _33.tiles, 'access', _34 => _34.get, 'call', _35 => _35(tk), 'optionalAccess', _36 => _36.data]), () => ( null)), "bake-all");
|
|
2095
2147
|
}
|
|
2096
2148
|
if (!out) continue;
|
|
2097
2149
|
const t = _chunk474IQG74cjs.finishTile.call(void 0, out, 4, 0);
|
|
@@ -2215,14 +2267,14 @@ var WetWorld = (_class = class {
|
|
|
2215
2267
|
display(id, maxTiles = Infinity) {
|
|
2216
2268
|
const lane = this.laneOf(id);
|
|
2217
2269
|
const keys = this.active.filter((k) => this.laneIndexOf(k) === lane.index);
|
|
2218
|
-
const stale = keys.filter((k) => _optionalChain([lane, 'access',
|
|
2219
|
-
stale.sort((a, b) => Number(lane.urgent.has(this.tileKeyOf(b))) - Number(lane.urgent.has(this.tileKeyOf(a))) || (_nullishCoalesce(_optionalChain([lane, 'access',
|
|
2270
|
+
const stale = keys.filter((k) => _optionalChain([lane, 'access', _37 => _37.shaded, 'access', _38 => _38.get, 'call', _39 => _39(this.tileKeyOf(k)), 'optionalAccess', _40 => _40.stamp]) !== lane.stamp);
|
|
2271
|
+
stale.sort((a, b) => Number(lane.urgent.has(this.tileKeyOf(b))) - Number(lane.urgent.has(this.tileKeyOf(a))) || (_nullishCoalesce(_optionalChain([lane, 'access', _41 => _41.shaded, 'access', _42 => _42.get, 'call', _43 => _43(this.tileKeyOf(a)), 'optionalAccess', _44 => _44.stamp]), () => ( 0))) - (_nullishCoalesce(_optionalChain([lane, 'access', _45 => _45.shaded, 'access', _46 => _46.get, 'call', _47 => _47(this.tileKeyOf(b)), 'optionalAccess', _48 => _48.stamp]), () => ( 0))));
|
|
2220
2272
|
const changed = [];
|
|
2221
2273
|
let done = 0;
|
|
2222
2274
|
for (const key of stale) {
|
|
2223
2275
|
if (done >= maxTiles) break;
|
|
2224
2276
|
const tk = this.tileKeyOf(key);
|
|
2225
|
-
const src = _nullishCoalesce(_optionalChain([lane, 'access',
|
|
2277
|
+
const src = _nullishCoalesce(_optionalChain([lane, 'access', _49 => _49.base, 'access', _50 => _50.tiles, 'access', _51 => _51.get, 'call', _52 => _52(tk), 'optionalAccess', _53 => _53.data]), () => ( null));
|
|
2226
2278
|
const out = this.shadeSlot(key, src, "display");
|
|
2227
2279
|
const tile = out ? _chunk474IQG74cjs.finishTile.call(void 0, out, 4, 0) : _nullishCoalesce(lane.base.tiles.get(tk), () => ( null));
|
|
2228
2280
|
lane.shaded.set(tk, { stamp: lane.stamp, tile: _nullishCoalesce(tile, () => ( { data: new Uint8ClampedArray(0), uniform: 0 })) });
|
|
@@ -2259,7 +2311,7 @@ var WetWorld = (_class = class {
|
|
|
2259
2311
|
for (const key2 of keys) {
|
|
2260
2312
|
const tk = this.tileKeyOf(key2);
|
|
2261
2313
|
live.add(tk);
|
|
2262
|
-
if (_optionalChain([lane, 'access',
|
|
2314
|
+
if (_optionalChain([lane, 'access', _54 => _54.lightShaded, 'access', _55 => _55.get, 'call', _56 => _56(tk), 'optionalAccess', _57 => _57.stamp]) === lane.stamp) continue;
|
|
2263
2315
|
const src = _nullishCoalesce(lane.light.tiles.get(tk), () => ( null));
|
|
2264
2316
|
const out = this.shadeLightSlot(key2, src, "display");
|
|
2265
2317
|
lane.lightShaded.set(tk, { stamp: lane.stamp, tile: out ? _chunk474IQG74cjs.finishTile.call(void 0, out, 1, 0) : src });
|
|
@@ -2457,7 +2509,7 @@ var WetWorld = (_class = class {
|
|
|
2457
2509
|
if (!this.gpu || this.busyFlag && !plan || !plan && !this.gpuDecide()) return { ...this.display(id, maxCpuTiles), gpu: false };
|
|
2458
2510
|
const lane = this.laneOf(id);
|
|
2459
2511
|
const keys = this.active.filter((k) => this.laneIndexOf(k) === lane.index);
|
|
2460
|
-
const stale = plan ? keys : keys.filter((k) => _optionalChain([lane, 'access',
|
|
2512
|
+
const stale = plan ? keys : keys.filter((k) => _optionalChain([lane, 'access', _58 => _58.shaded, 'access', _59 => _59.get, 'call', _60 => _60(this.tileKeyOf(k)), 'optionalAccess', _61 => _61.stamp]) !== lane.stamp);
|
|
2461
2513
|
if (!stale.length) return { ...this.display(id, 0), gpu: true };
|
|
2462
2514
|
let tiles;
|
|
2463
2515
|
const stamp = lane.stamp;
|
|
@@ -2465,7 +2517,7 @@ var WetWorld = (_class = class {
|
|
|
2465
2517
|
try {
|
|
2466
2518
|
if (!plan) this.gpuSync();
|
|
2467
2519
|
const parity = plan ? plan.parity + plan.done & 1 : this.parity;
|
|
2468
|
-
tiles = await this.gpu.shade(this.gpuJobs(stale), parity, stale.map((k) => _nullishCoalesce(_optionalChain([base, 'access',
|
|
2520
|
+
tiles = await this.gpu.shade(this.gpuJobs(stale), parity, stale.map((k) => _nullishCoalesce(_optionalChain([base, 'access', _62 => _62.tiles, 'access', _63 => _63.get, 'call', _64 => _64(this.tileKeyOf(k)), 'optionalAccess', _65 => _65.data]), () => ( null))), [this.paperBytes[0], this.paperBytes[1], this.paperBytes[2]]);
|
|
2469
2521
|
} catch (e) {
|
|
2470
2522
|
this.gpuStop(`Wet paint stopped using the GPU (${e.message}).`);
|
|
2471
2523
|
return { ...this.display(id, maxCpuTiles), gpu: false };
|
|
@@ -2644,8 +2696,8 @@ function normalizeFlow(raw = {}, base = DEFAULT_FLOW) {
|
|
|
2644
2696
|
}
|
|
2645
2697
|
function flowField(spec, width, height) {
|
|
2646
2698
|
const k = FLOW_ACCEL;
|
|
2647
|
-
const cx = _nullishCoalesce(_optionalChain([spec, 'access',
|
|
2648
|
-
const cy = _nullishCoalesce(_optionalChain([spec, 'access',
|
|
2699
|
+
const cx = _nullishCoalesce(_optionalChain([spec, 'access', _66 => _66.center, 'optionalAccess', _67 => _67.x]), () => ( width / 2));
|
|
2700
|
+
const cy = _nullishCoalesce(_optionalChain([spec, 'access', _68 => _68.center, 'optionalAccess', _69 => _69.y]), () => ( height / 2));
|
|
2649
2701
|
const r0 = Math.max(width, height) / 2;
|
|
2650
2702
|
switch (spec.kind) {
|
|
2651
2703
|
case "none":
|
|
@@ -3108,7 +3160,7 @@ var UNIFORM = 64;
|
|
|
3108
3160
|
var STORAGE = 128;
|
|
3109
3161
|
function findWebGpu() {
|
|
3110
3162
|
const nav = globalThis.navigator;
|
|
3111
|
-
return _nullishCoalesce(_optionalChain([nav, 'optionalAccess',
|
|
3163
|
+
return _nullishCoalesce(_optionalChain([nav, 'optionalAccess', _70 => _70.gpu]), () => ( null));
|
|
3112
3164
|
}
|
|
3113
3165
|
async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
3114
3166
|
const no = (reason, adapter2 = null) => ({ engine: null, support: { supported: false, reason, adapter: adapter2, maxSlots: 0 } });
|
|
@@ -3120,7 +3172,7 @@ async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
|
3120
3172
|
return no(`WebGPU gave no adapter (${e.message}); wet paint runs on the CPU.`);
|
|
3121
3173
|
}
|
|
3122
3174
|
if (!adapter) return no("WebGPU gave no adapter (the GPU may be blocklisted); wet paint runs on the CPU.");
|
|
3123
|
-
const name = [_optionalChain([adapter, 'access',
|
|
3175
|
+
const name = [_optionalChain([adapter, 'access', _71 => _71.info, 'optionalAccess', _72 => _72.vendor]), _optionalChain([adapter, 'access', _73 => _73.info, 'optionalAccess', _74 => _74.architecture])].filter(Boolean).join(" ") || null;
|
|
3124
3176
|
const binding = Math.min(_nullishCoalesce(adapter.limits.maxStorageBufferBindingSize, () => ( 0)), _nullishCoalesce(adapter.limits.maxBufferSize, () => ( 0)));
|
|
3125
3177
|
const maxSlots = Math.min(MAX_WET_SLOTS, Math.floor(binding / SLOT_BYTES));
|
|
3126
3178
|
if (maxSlots < 4) return no(`The GPU's storage buffers hold ${Math.max(0, maxSlots)} wet tiles; at least 4 are needed. Wet paint runs on the CPU.`, name);
|
|
@@ -3140,27 +3192,27 @@ async function createWetGpuEngine(gpu = findWebGpu()) {
|
|
|
3140
3192
|
const engine = await WetGpuEngine.start(device, maxSlots, name);
|
|
3141
3193
|
return { engine, support: { supported: true, reason: null, adapter: name, maxSlots } };
|
|
3142
3194
|
} catch (e) {
|
|
3143
|
-
_optionalChain([device, 'access',
|
|
3195
|
+
_optionalChain([device, 'access', _75 => _75.destroy, 'optionalCall', _76 => _76()]);
|
|
3144
3196
|
return no(`The wet-media shaders did not compile on this GPU (${e.message}); wet paint runs on the CPU.`, name);
|
|
3145
3197
|
}
|
|
3146
3198
|
}
|
|
3147
3199
|
async function wetGpuSupport(gpu = findWebGpu()) {
|
|
3148
3200
|
const { engine, support } = await createWetGpuEngine(gpu);
|
|
3149
|
-
_optionalChain([engine, 'optionalAccess',
|
|
3201
|
+
_optionalChain([engine, 'optionalAccess', _77 => _77.destroy, 'call', _78 => _78()]);
|
|
3150
3202
|
return support;
|
|
3151
3203
|
}
|
|
3152
3204
|
async function pipeline(device, code, label) {
|
|
3153
|
-
_optionalChain([device, 'access',
|
|
3205
|
+
_optionalChain([device, 'access', _79 => _79.pushErrorScope, 'optionalCall', _80 => _80("validation")]);
|
|
3154
3206
|
const module = device.createShaderModule({ code, label });
|
|
3155
|
-
const info = await _optionalChain([module, 'access',
|
|
3156
|
-
const errors = _nullishCoalesce(_optionalChain([info, 'optionalAccess',
|
|
3207
|
+
const info = await _optionalChain([module, 'access', _81 => _81.getCompilationInfo, 'optionalCall', _82 => _82()]);
|
|
3208
|
+
const errors = _nullishCoalesce(_optionalChain([info, 'optionalAccess', _83 => _83.messages, 'access', _84 => _84.filter, 'call', _85 => _85((m) => m.type === "error")]), () => ( []));
|
|
3157
3209
|
if (errors.length) {
|
|
3158
|
-
await _optionalChain([device, 'access',
|
|
3210
|
+
await _optionalChain([device, 'access', _86 => _86.popErrorScope, 'optionalCall', _87 => _87()]);
|
|
3159
3211
|
throw new Error(`${label}: ${errors.map((m) => `line ${m.lineNum}: ${m.message}`).join("; ")}`);
|
|
3160
3212
|
}
|
|
3161
3213
|
const desc = { layout: "auto", compute: { module, entryPoint: "main" }, label };
|
|
3162
3214
|
const p = device.createComputePipelineAsync ? await device.createComputePipelineAsync(desc) : device.createComputePipeline(desc);
|
|
3163
|
-
const err = await _optionalChain([device, 'access',
|
|
3215
|
+
const err = await _optionalChain([device, 'access', _88 => _88.popErrorScope, 'optionalCall', _89 => _89()]);
|
|
3164
3216
|
if (err) throw new Error(`${label}: ${err.message}`);
|
|
3165
3217
|
return p;
|
|
3166
3218
|
}
|
|
@@ -3186,8 +3238,8 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3186
3238
|
return b;
|
|
3187
3239
|
});
|
|
3188
3240
|
this.shadeUni = d.createBuffer({ size: 16, usage: UNIFORM | COPY_DST, label: "wet shade" });
|
|
3189
|
-
void _optionalChain([device, 'access',
|
|
3190
|
-
this.lostReason = _optionalChain([info, 'optionalAccess',
|
|
3241
|
+
void _optionalChain([device, 'access', _90 => _90.lost, 'optionalAccess', _91 => _91.then, 'call', _92 => _92((info) => {
|
|
3242
|
+
this.lostReason = _optionalChain([info, 'optionalAccess', _93 => _93.message]) || _optionalChain([info, 'optionalAccess', _94 => _94.reason]) || "the GPU device was lost";
|
|
3191
3243
|
})]);
|
|
3192
3244
|
}
|
|
3193
3245
|
|
|
@@ -3221,7 +3273,7 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3221
3273
|
}
|
|
3222
3274
|
/** Bytes of GPU memory in use. */
|
|
3223
3275
|
memoryBytes() {
|
|
3224
|
-
return this.state.size + this.jobs.size + (_nullishCoalesce(_optionalChain([this, 'access',
|
|
3276
|
+
return this.state.size + this.jobs.size + (_nullishCoalesce(_optionalChain([this, 'access', _95 => _95.srcTiles, 'optionalAccess', _96 => _96.size]), () => ( 0))) + (_nullishCoalesce(_optionalChain([this, 'access', _97 => _97.outTiles, 'optionalAccess', _98 => _98.size]), () => ( 0))) * 2;
|
|
3225
3277
|
}
|
|
3226
3278
|
/** Slots the state buffer holds now. */
|
|
3227
3279
|
get capacity() {
|
|
@@ -3370,9 +3422,9 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3370
3422
|
const d = this.device;
|
|
3371
3423
|
const tileBytes = TILE_WORDS * 4;
|
|
3372
3424
|
if (n > this.tileCap || !this.outTiles || !this.outRead || !this.srcTiles) {
|
|
3373
|
-
_optionalChain([this, 'access',
|
|
3374
|
-
_optionalChain([this, 'access',
|
|
3375
|
-
_optionalChain([this, 'access',
|
|
3425
|
+
_optionalChain([this, 'access', _99 => _99.srcTiles, 'optionalAccess', _100 => _100.destroy, 'call', _101 => _101()]);
|
|
3426
|
+
_optionalChain([this, 'access', _102 => _102.outTiles, 'optionalAccess', _103 => _103.destroy, 'call', _104 => _104()]);
|
|
3427
|
+
_optionalChain([this, 'access', _105 => _105.outRead, 'optionalAccess', _106 => _106.destroy, 'call', _107 => _107()]);
|
|
3376
3428
|
this.tileCap = Math.max(n, this.tileCap * 2, 4);
|
|
3377
3429
|
this.srcTiles = d.createBuffer({ size: this.tileCap * tileBytes, usage: STORAGE | COPY_DST, label: "wet base tiles" });
|
|
3378
3430
|
this.outTiles = d.createBuffer({ size: this.tileCap * tileBytes, usage: STORAGE | COPY_SRC, label: "wet shaded tiles" });
|
|
@@ -3426,7 +3478,7 @@ var WetGpuEngine = (_class3 = class _WetGpuEngine {
|
|
|
3426
3478
|
return this.device.queue.onSubmittedWorkDone();
|
|
3427
3479
|
}
|
|
3428
3480
|
destroy() {
|
|
3429
|
-
for (const b of [this.state, this.params, this.jobs, this.flags, this.flagsRead, ...this.uni, this.shadeUni, this.srcTiles, this.outTiles, this.outRead]) _optionalChain([b, 'optionalAccess',
|
|
3481
|
+
for (const b of [this.state, this.params, this.jobs, this.flags, this.flagsRead, ...this.uni, this.shadeUni, this.srcTiles, this.outTiles, this.outRead]) _optionalChain([b, 'optionalAccess', _108 => _108.destroy, 'call', _109 => _109()]);
|
|
3430
3482
|
this.device.destroy();
|
|
3431
3483
|
}
|
|
3432
3484
|
}, _class3);
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
resolveEngine,
|
|
28
28
|
summarizeBrushSource,
|
|
29
29
|
withKeptIssues
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-ZM7IKQ4X.js";
|
|
31
31
|
import {
|
|
32
32
|
base64ToBytes
|
|
33
33
|
} from "./chunk-OTTT5N3K.js";
|
|
@@ -44,7 +44,7 @@ var BRUSH_PATCH_PROPERTIES = (() => {
|
|
|
44
44
|
const { required: _r, ...tip } = rest.tip;
|
|
45
45
|
return { ...rest, tip: { ...tip, description: `${tip.description} In a patch, shape may be left out to keep it.` } };
|
|
46
46
|
})();
|
|
47
|
-
var UNSETTABLE_BRUSH_FACETS = ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "ghost", "motion", "colour"];
|
|
47
|
+
var UNSETTABLE_BRUSH_FACETS = ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "motion", "colour"];
|
|
48
48
|
var BRUSH_UNSET_PROPERTY = {
|
|
49
49
|
type: "array",
|
|
50
50
|
minItems: 1,
|
|
@@ -1113,6 +1113,11 @@ var BRUSH_SLIDERS = [
|
|
|
1113
1113
|
{ path: "dynamics.velocitySize", label: "Speed size", min: -1, max: 1, step: 0.01 }
|
|
1114
1114
|
];
|
|
1115
1115
|
var LIGHT_SLIDER = { path: "light.amount", label: "Light", min: 0, max: 1, step: 0.01 };
|
|
1116
|
+
var IRIDESCENCE_SLIDERS = [
|
|
1117
|
+
{ path: "iridescence.thickness", label: "Film thickness (nm)", min: 100, max: 1e3, step: 5 },
|
|
1118
|
+
{ path: "iridescence.pressureToThickness", label: "Pressure \u2192 thickness", min: 0, max: 1, step: 0.01 },
|
|
1119
|
+
{ path: "iridescence.ior", label: "Refractive index", min: 1.2, max: 2, step: 0.01 }
|
|
1120
|
+
];
|
|
1116
1121
|
var PICKUP_SLIDERS = [
|
|
1117
1122
|
{ path: "behavior.pickup", label: "Pick-up", min: 0, max: 1, step: 0.01 },
|
|
1118
1123
|
{ path: "behavior.mix", label: "Mix", min: 0, max: 1, step: 0.01 }
|
|
@@ -1121,12 +1126,22 @@ var GHOST_SLIDERS = [
|
|
|
1121
1126
|
{ path: "ghost.linger", label: "Linger", min: 0.5, max: 60, step: 0.5 },
|
|
1122
1127
|
{ path: "ghost.smear", label: "Smear", min: 0, max: 1, step: 0.01 }
|
|
1123
1128
|
];
|
|
1129
|
+
var MUTATION_SLIDERS = [
|
|
1130
|
+
{ path: "mutation.settle", label: "Settle", min: 0.5, max: 10, step: 0.5 },
|
|
1131
|
+
{ path: "mutation.patience", label: "Patience", min: 5, max: 300, step: 5 },
|
|
1132
|
+
{ path: "mutation.fade", label: "Fade", min: 0.5, max: 10, step: 0.5 }
|
|
1133
|
+
];
|
|
1124
1134
|
function brushEngineControls(brush) {
|
|
1125
1135
|
const c = engineControls(brush);
|
|
1126
|
-
|
|
1127
|
-
|
|
1136
|
+
if (!c) return null;
|
|
1137
|
+
const mut = brush.mutation ? MUTATION_SLIDERS : [];
|
|
1138
|
+
const wetPaint = brush.engine === "wet" && brush.wet?.tool === "paint" && !brush.ghost && !brush.mutation;
|
|
1139
|
+
if (!(wetPaint || ["dab", "mixer", "particle", "bristle", "impasto"].includes(brush.engine))) {
|
|
1140
|
+
return mut.length ? { ...c, sliders: [...c.sliders, ...mut] } : c;
|
|
1141
|
+
}
|
|
1128
1142
|
const extra = brush.engine === "impasto" ? [{ path: "impasto.rim", label: "Rim", min: 0, max: 1, step: 0.01 }, { path: "impasto.clarity", label: "Clarity", min: 0, max: 1, step: 0.01 }] : [];
|
|
1129
|
-
|
|
1143
|
+
const film = brush.iridescence ? IRIDESCENCE_SLIDERS : [];
|
|
1144
|
+
return { ...c, sliders: [...c.sliders, ...mut, LIGHT_SLIDER, ...extra, ...film], light: true, iridescence: true };
|
|
1130
1145
|
}
|
|
1131
1146
|
function engineControls(brush) {
|
|
1132
1147
|
switch (brush.engine) {
|
|
@@ -1197,17 +1212,17 @@ function engineControls(brush) {
|
|
|
1197
1212
|
{ path: "impasto.load", label: "Load", min: 0, max: 1, step: 0.01 },
|
|
1198
1213
|
{ path: "impasto.thinner", label: "Thinner", min: 0, max: 1, step: 0.01 },
|
|
1199
1214
|
{ path: "impasto.drag", label: "Drag", min: 0, max: 1, step: 0.01 },
|
|
1200
|
-
...PICKUP_SLIDERS
|
|
1215
|
+
...brush.mutation ? [] : PICKUP_SLIDERS
|
|
1201
1216
|
],
|
|
1202
1217
|
mixingPath: "behavior.mixing",
|
|
1203
|
-
dirty:
|
|
1218
|
+
dirty: !brush.mutation,
|
|
1204
1219
|
multicolor: false,
|
|
1205
|
-
load:
|
|
1220
|
+
load: !brush.mutation,
|
|
1206
1221
|
impastoTool: true
|
|
1207
1222
|
};
|
|
1208
1223
|
case "wet": {
|
|
1209
1224
|
const tool = brush.wet?.tool ?? "paint";
|
|
1210
|
-
const ghost = tool === "paint" && Boolean(brush.ghost);
|
|
1225
|
+
const ghost = tool === "paint" && (Boolean(brush.ghost) || Boolean(brush.mutation));
|
|
1211
1226
|
const sliders = tool === "paint" ? [
|
|
1212
1227
|
{ path: "wet.water", label: "Water", min: 0, max: 1, step: 0.01 },
|
|
1213
1228
|
{ path: "wet.pigment", label: "Pigment", min: 0, max: 1, step: 0.01 },
|
|
@@ -1215,7 +1230,7 @@ function engineControls(brush) {
|
|
|
1215
1230
|
{ path: "wet.rewet", label: "Re-wet", min: 0, max: 1, step: 0.01 },
|
|
1216
1231
|
{ path: "wet.load", label: "Load", min: 0, max: 1, step: 0.01 },
|
|
1217
1232
|
{ path: "wet.thinner", label: "Thinner", min: 0, max: 1, step: 0.01 },
|
|
1218
|
-
...ghost ? GHOST_SLIDERS : PICKUP_SLIDERS
|
|
1233
|
+
...brush.mutation ? [{ path: "ghost.smear", label: "Smear", min: 0, max: 1, step: 0.01 }] : ghost ? GHOST_SLIDERS : PICKUP_SLIDERS
|
|
1219
1234
|
] : tool === "water" ? [
|
|
1220
1235
|
{ path: "wet.water", label: "Water", min: 0, max: 1, step: 0.01 },
|
|
1221
1236
|
{ path: "wet.rewet", label: "Re-wet", min: 0, max: 1, step: 0.01 }
|
|
@@ -1249,7 +1264,7 @@ function engineControls(brush) {
|
|
|
1249
1264
|
case "mixer":
|
|
1250
1265
|
return { title: "Mixer Brush", sliders: [...PICKUP_SLIDERS, { path: "mixer.load", label: "Load", min: 0, max: 1, step: 0.01 }], mixingPath: "behavior.mixing", dirty: true, multicolor: true, load: true };
|
|
1251
1266
|
case "dab":
|
|
1252
|
-
return { title: "Paint behaviour", sliders: PICKUP_SLIDERS, mixingPath: "behavior.mixing", dirty:
|
|
1267
|
+
return { title: "Paint behaviour", sliders: brush.mutation ? [] : PICKUP_SLIDERS, mixingPath: "behavior.mixing", dirty: !brush.mutation, multicolor: !brush.mutation, load: !brush.mutation };
|
|
1253
1268
|
default:
|
|
1254
1269
|
return null;
|
|
1255
1270
|
}
|
|
@@ -1289,7 +1304,9 @@ export {
|
|
|
1289
1304
|
createBrushLibraryTools,
|
|
1290
1305
|
createBrushLibraryToolProvider,
|
|
1291
1306
|
BRUSH_SLIDERS,
|
|
1307
|
+
IRIDESCENCE_SLIDERS,
|
|
1292
1308
|
GHOST_SLIDERS,
|
|
1309
|
+
MUTATION_SLIDERS,
|
|
1293
1310
|
brushEngineControls,
|
|
1294
1311
|
multiColorSliders,
|
|
1295
1312
|
patchBrushValue
|
|
@@ -74,7 +74,7 @@ function profileAlongPolyline(points, values, count = 32) {
|
|
|
74
74
|
var round3 = (v) => Math.round(v * 1e3) / 1e3;
|
|
75
75
|
var loading = null;
|
|
76
76
|
function loadCanvasBrushstrokeRenderer() {
|
|
77
|
-
loading ??= import("./brushstrokeRender-
|
|
77
|
+
loading ??= import("./brushstrokeRender-WGY4DZHF.js").catch((error) => {
|
|
78
78
|
loading = null;
|
|
79
79
|
throw error;
|
|
80
80
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunk6QNDGMK7cjs = require('./chunk-6QNDGMK7.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var _chunkJBZRVLXVcjs = require('./chunk-JBZRVLXV.cjs');
|
|
@@ -33,25 +33,25 @@ var BRUSH_PREVIEW_FALLBACKS = {
|
|
|
33
33
|
tools: { light: "#475569", dark: "#cbd5e1" }
|
|
34
34
|
};
|
|
35
35
|
function brushPreviewsOnDark(brush) {
|
|
36
|
-
return (_nullishCoalesce(_optionalChain([brush, 'access', _ => _.light, 'optionalAccess', _2 => _2.amount]), () => ( 0))) > 0
|
|
36
|
+
return ((_nullishCoalesce(_optionalChain([brush, 'access', _ => _.light, 'optionalAccess', _2 => _2.amount]), () => ( 0))) > 0 || (_nullishCoalesce(_optionalChain([brush, 'access', _3 => _3.fluorescence, 'optionalAccess', _4 => _4.amount]), () => ( 0))) > 0) && _optionalChain([brush, 'access', _5 => _5.tip, 'optionalAccess', _6 => _6.blend]) !== "multiply";
|
|
37
37
|
}
|
|
38
38
|
var hexOf = (c) => _nullishCoalesce(_chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "light"), () => ( "#ffffff"));
|
|
39
39
|
function brushPreviewStrength(brush) {
|
|
40
40
|
const opacity = _nullishCoalesce(brush.tip.opacity, () => ( 1));
|
|
41
41
|
const flow = _nullishCoalesce(brush.tip.flow, () => ( 1));
|
|
42
|
-
const grain = _nullishCoalesce(_optionalChain([brush, 'access',
|
|
42
|
+
const grain = _nullishCoalesce(_optionalChain([brush, 'access', _7 => _7.behaviour, 'optionalAccess', _8 => _8.grain]), () => ( 0));
|
|
43
43
|
return Math.max(0.25, Math.min(1, 0.85 * opacity * (0.6 + 0.4 * flow) * (1 - 0.3 * grain)));
|
|
44
44
|
}
|
|
45
45
|
var over = (fg, bg, alpha) => ({ r: fg.r * alpha + bg.r * (1 - alpha), g: fg.g * alpha + bg.g * (1 - alpha), b: fg.b * alpha + bg.b * (1 - alpha), a: 1 });
|
|
46
46
|
function brushPreviewColours(brush, options = {}) {
|
|
47
|
-
const profile = _nullishCoalesce(options.profile, () => (
|
|
47
|
+
const profile = _nullishCoalesce(options.profile, () => ( _chunk6QNDGMK7cjs.PAINT_PROFILE));
|
|
48
48
|
let background = profile.light === "full" && brushPreviewsOnDark(brush) ? BRUSH_PREVIEW_DARK_PAPER : hexOf(_nullishCoalesce(options.paper, () => ( "#ffffff")));
|
|
49
49
|
if (!options.keepPaper && brush.tip.blend === "multiply" && _chunk5UEFBM2Mcjs.relativeLuminance.call(void 0, _chunk5UEFBM2Mcjs.parseColor.call(void 0, background)) < 0.18) background = "#ffffff";
|
|
50
50
|
const bg = _chunk5UEFBM2Mcjs.parseColor.call(void 0, background);
|
|
51
51
|
const scheme = _chunk5UEFBM2Mcjs.relativeLuminance.call(void 0, bg) < 0.18 ? "dark" : "light";
|
|
52
|
-
const own = brush.kind === "mark" ? _optionalChain([brush, 'access',
|
|
52
|
+
const own = brush.kind === "mark" ? _optionalChain([brush, 'access', _9 => _9.colour, 'optionalAccess', _10 => _10.default]) : void 0;
|
|
53
53
|
const ownHex = typeof own === "string" || _chunkMLLTWAXHcjs.isDualColor.call(void 0, own) ? _chunkJBZRVLXVcjs.brushColourHex.call(void 0, own, scheme) : null;
|
|
54
|
-
if (ownHex && brush.tip.blend === "multiply" && (_nullishCoalesce(_optionalChain([brush, 'access',
|
|
54
|
+
if (ownHex && brush.tip.blend === "multiply" && (_nullishCoalesce(_optionalChain([brush, 'access', _11 => _11.light, 'optionalAccess', _12 => _12.amount]), () => ( 0))) > 0 && scheme === "light") return { background, color: ownHex, scheme };
|
|
55
55
|
const group = brush.kind === "tool" ? "tools" : _nullishCoalesce(brush.medium, () => ( "other"));
|
|
56
56
|
const color = _nullishCoalesce(ownHex, () => ( _chunkJBZRVLXVcjs.brushColourHex.call(void 0, _nullishCoalesce(BRUSH_PREVIEW_FALLBACKS[group], () => ( BRUSH_PREVIEW_FALLBACKS.other)), scheme)));
|
|
57
57
|
const alpha = brushPreviewStrength(brush);
|
|
@@ -850,7 +850,7 @@ var S2 = SLOT_SIDE;
|
|
|
850
850
|
var SNAP_PLANES = SET_PLANES + MASS_CHANNELS;
|
|
851
851
|
var noLight = () => new TiledSurface(1, /* @__PURE__ */ new Map(), 0);
|
|
852
852
|
function cloneGhost(g) {
|
|
853
|
-
return g ? { pigment: [...g.pigment], remaining: g.remaining, total: g.total, linger: g.linger } : null;
|
|
853
|
+
return g ? { pigment: [...g.pigment], remaining: g.remaining, total: g.total, linger: g.linger, ...g.trigger === "agent" ? { trigger: "agent" } : {} } : null;
|
|
854
854
|
}
|
|
855
855
|
function newLane(id, index, params, flow, flowStrength, base, light, ghost) {
|
|
856
856
|
const l = light ?? noLight();
|
|
@@ -1119,21 +1119,59 @@ var WetWorld = class {
|
|
|
1119
1119
|
}
|
|
1120
1120
|
/**
|
|
1121
1121
|
* Starts a ghost paint fade on `id` with `pigment` per unit tracer and `linger` seconds. If an
|
|
1122
|
-
* earlier ghost of a different colour is still fading on the layer, it finishes at once first
|
|
1122
|
+
* earlier ghost of a different colour is still fading on the layer, it finishes at once first
|
|
1123
|
+
* (or keeps its paint when it was an unclaimed agent-triggered ghost).
|
|
1123
1124
|
*/
|
|
1124
|
-
startGhost(id, pigment, linger, stepsPerSecond = 120) {
|
|
1125
|
+
startGhost(id, pigment, linger, stepsPerSecond = 120, trigger = "immediate") {
|
|
1125
1126
|
this.requireIdle();
|
|
1126
1127
|
const lane = this.laneOf(id);
|
|
1127
1128
|
const p = [Math.fround(pigment[0]), Math.fround(pigment[1]), Math.fround(pigment[2]), Math.fround(pigment[3])];
|
|
1128
1129
|
if (lane.ghost) {
|
|
1129
1130
|
const g = lane.ghost.pigment;
|
|
1130
1131
|
const same = Math.abs(g[0] - p[0]) <= 1e-6 && Math.abs(g[1] - p[1]) <= 1e-6 && Math.abs(g[2] - p[2]) <= 1e-6 && Math.abs(g[3] - p[3]) <= 1e-6;
|
|
1131
|
-
if (!same)
|
|
1132
|
+
if (!same) {
|
|
1133
|
+
if (lane.ghost.trigger === "agent") this.keepGhost(id);
|
|
1134
|
+
else this.fadeGhost(id, 1);
|
|
1135
|
+
}
|
|
1132
1136
|
}
|
|
1133
1137
|
const total = Math.max(1, Math.round(linger * stepsPerSecond / FREE_INTERVAL));
|
|
1134
|
-
lane.ghost = { pigment: p, remaining: total, total, linger };
|
|
1138
|
+
lane.ghost = { pigment: p, remaining: total, total, linger, ...trigger === "agent" ? { trigger: "agent" } : {} };
|
|
1135
1139
|
lane.lit = false;
|
|
1136
1140
|
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Releases a held (`trigger: 'agent'`) ghost on `id` so its fade starts counting down on the
|
|
1143
|
+
* simulation clock over `linger` seconds (default: the lane's configured `linger`).
|
|
1144
|
+
*/
|
|
1145
|
+
releaseGhost(id, linger, stepsPerSecond = 120) {
|
|
1146
|
+
this.requireIdle();
|
|
1147
|
+
const lane = this.laneOf(id);
|
|
1148
|
+
if (!lane.ghost) return;
|
|
1149
|
+
const l = linger ?? lane.ghost.linger;
|
|
1150
|
+
const total = Math.max(1, Math.round(l * stepsPerSecond / FREE_INTERVAL));
|
|
1151
|
+
lane.ghost = { pigment: lane.ghost.pigment, remaining: total, total, linger: l };
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Drops a ghost lane's tracer (`P_L`, `P_DL`) without subtracting its pigment, so an unclaimed
|
|
1155
|
+
* or declined wet mutation stroke stays as ordinary wet paint.
|
|
1156
|
+
*/
|
|
1157
|
+
keepGhost(id) {
|
|
1158
|
+
this.requireIdle();
|
|
1159
|
+
const lane = this.laneOf(id);
|
|
1160
|
+
if (!lane.ghost) return;
|
|
1161
|
+
const f = this.f32;
|
|
1162
|
+
for (const key of this.active) {
|
|
1163
|
+
if (this.laneIndexOf(key) !== lane.index) continue;
|
|
1164
|
+
const slot = this.slotOf(key);
|
|
1165
|
+
if (slot < 0) continue;
|
|
1166
|
+
const b = this.slotBase(slot);
|
|
1167
|
+
const cur = b + this.parity * SET_PLANES * PLANE;
|
|
1168
|
+
f.fill(0, cur + P_L * PLANE, cur + (P_L + 1) * PLANE);
|
|
1169
|
+
f.fill(0, b + P_DL * PLANE, b + (P_DL + 1) * PLANE);
|
|
1170
|
+
this.gpuDirtySlot(slot, 1, WET_TILE);
|
|
1171
|
+
}
|
|
1172
|
+
lane.ghost = null;
|
|
1173
|
+
this.refreshHalos();
|
|
1174
|
+
}
|
|
1137
1175
|
pack(lane) {
|
|
1138
1176
|
packWetParams(lane.params, this.paper ?? DEFAULT_WET_PAPER, this.tilt, lane.flowStrength, this.prm);
|
|
1139
1177
|
this.f32.set(this.prm, this.layout.params + lane.index * PARAM_FLOATS * 4 >> 2);
|
|
@@ -1367,7 +1405,7 @@ var WetWorld = class {
|
|
|
1367
1405
|
for (const key of wakeups) woke = this.activate(key) || woke;
|
|
1368
1406
|
if (this.clock % FREE_INTERVAL === 0) {
|
|
1369
1407
|
for (const lane of this.lanes) {
|
|
1370
|
-
if (!lane?.ghost) continue;
|
|
1408
|
+
if (!lane?.ghost || lane.ghost.trigger === "agent") continue;
|
|
1371
1409
|
const g = lane.ghost;
|
|
1372
1410
|
const amount = g.remaining <= 1 ? 1 : 1 / g.remaining;
|
|
1373
1411
|
g.remaining = Math.max(0, g.remaining - 1);
|
|
@@ -1931,12 +1969,16 @@ var WetWorld = class {
|
|
|
1931
1969
|
continue;
|
|
1932
1970
|
}
|
|
1933
1971
|
const f = this.f32;
|
|
1934
|
-
const pig = lane.ghost
|
|
1972
|
+
const pig = lane.ghost && lane.ghost.trigger !== "agent" ? lane.ghost.pigment : null;
|
|
1973
|
+
const clearTracer = Boolean(lane.ghost && lane.ghost.trigger === "agent");
|
|
1935
1974
|
for (let y = y0; y < y1; y++) {
|
|
1936
1975
|
for (let x = x0; x < x1; x++) {
|
|
1937
1976
|
const c = this.cell(lane, x, y);
|
|
1938
1977
|
const d = this.single(c) + P_D0 * PLANE;
|
|
1939
|
-
if (
|
|
1978
|
+
if (clearTracer) {
|
|
1979
|
+
f[c + P_L * PLANE] = 0;
|
|
1980
|
+
f[d + 4 * PLANE] = 0;
|
|
1981
|
+
} else if (pig) {
|
|
1940
1982
|
const tl = f[c + P_L * PLANE];
|
|
1941
1983
|
const dl = f[d + 4 * PLANE];
|
|
1942
1984
|
if (tl > 0 || dl > 0) {
|
|
@@ -1980,7 +2022,17 @@ var WetWorld = class {
|
|
|
1980
2022
|
bakeKey(key, all) {
|
|
1981
2023
|
const lane = this.lanes[this.laneIndexOf(key)];
|
|
1982
2024
|
if (lane.ghost) {
|
|
1983
|
-
|
|
2025
|
+
if (lane.ghost.trigger === "agent") {
|
|
2026
|
+
const slot = this.slotOf(key);
|
|
2027
|
+
if (slot >= 0) {
|
|
2028
|
+
const b = this.slotBase(slot);
|
|
2029
|
+
const cur = b + this.parity * SET_PLANES * PLANE;
|
|
2030
|
+
this.f32.fill(0, cur + P_L * PLANE, cur + (P_L + 1) * PLANE);
|
|
2031
|
+
this.f32.fill(0, b + P_DL * PLANE, b + (P_DL + 1) * PLANE);
|
|
2032
|
+
}
|
|
2033
|
+
} else {
|
|
2034
|
+
this.fadeGhostKey(key, lane, 1);
|
|
2035
|
+
}
|
|
1984
2036
|
if (!this.hasGhostTracer(lane)) lane.ghost = null;
|
|
1985
2037
|
}
|
|
1986
2038
|
const [tx, ty] = this.tileXY(key);
|
|
@@ -2062,7 +2114,7 @@ var WetWorld = class {
|
|
|
2062
2114
|
if (this.laneIndexOf(key) !== lane.index) continue;
|
|
2063
2115
|
const tk = this.tileKeyOf(key);
|
|
2064
2116
|
let out;
|
|
2065
|
-
if (lane.ghost) {
|
|
2117
|
+
if (lane.ghost && lane.ghost.trigger !== "agent") {
|
|
2066
2118
|
const b = this.slotBase(this.slotOf(key));
|
|
2067
2119
|
const cur = b + this.parity * SET_PLANES * PLANE;
|
|
2068
2120
|
const savedP = this.f32.slice(cur + P_P0 * PLANE, cur + (P_P0 + MASS_CHANNELS) * PLANE);
|