@pixerate/editor 0.271.0 → 0.272.1
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/agent/index.cjs +34 -32
- package/dist/agent/index.js +10 -8
- package/dist/animation-editor/index.cjs +60 -60
- package/dist/animation-editor/index.js +4 -4
- package/dist/brushes/index.cjs +69 -66
- package/dist/brushes/index.js +6 -3
- package/dist/brushes/patch.d.cts +1 -1
- package/dist/brushes/patch.d.ts +1 -1
- package/dist/brushes/schema.d.cts +1 -0
- package/dist/brushes/schema.d.ts +1 -0
- package/dist/brushes/types.d.cts +8 -0
- package/dist/brushes/types.d.ts +8 -0
- package/dist/{brushstrokeRender-WR2N5HHY.cjs → brushstrokeRender-5YBCLFDQ.cjs} +15 -15
- package/dist/{brushstrokeRender-A727TTNQ.js → brushstrokeRender-DZGFU3J4.js} +3 -3
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/chart/contract.d.cts +95 -0
- package/dist/chart/contract.d.ts +95 -0
- package/dist/chart/controller.d.cts +4 -0
- package/dist/chart/controller.d.ts +4 -0
- package/dist/chart/index.cjs +492 -26
- package/dist/chart/index.d.cts +1 -0
- package/dist/chart/index.d.ts +1 -0
- package/dist/chart/index.js +476 -10
- package/dist/chart/tools.d.cts +3 -0
- package/dist/chart/tools.d.ts +3 -0
- package/dist/chart-maps/index.cjs +4 -64
- package/dist/chart-maps/index.js +3 -63
- package/dist/{chunk-YNFSH72F.js → chunk-2F3YDXCN.js} +1 -1
- package/dist/{chunk-QYXUE37Q.js → chunk-2XDNF73E.js} +1 -1
- package/dist/{chunk-3KNQ2W6X.cjs → chunk-3JKCREEU.cjs} +59 -53
- package/dist/{chunk-NMZQMPFZ.js → chunk-4LZQO5Y7.js} +2 -0
- package/dist/{chunk-B5W677L7.js → chunk-5HP2VSAS.js} +1 -1
- package/dist/chunk-5UGRMVNE.js +328 -0
- package/dist/{chunk-X4FTNFIA.js → chunk-7MGPW2OV.js} +1 -1
- package/dist/{chunk-BPJSI4NT.cjs → chunk-7W2EQQBP.cjs} +2 -2
- package/dist/{chunk-DGITFN73.cjs → chunk-BWJBZAUE.cjs} +8 -8
- package/dist/chunk-CHZYVNXZ.js +336 -0
- package/dist/{chunk-LETF75CA.js → chunk-CLB2I2FU.js} +1 -1
- package/dist/chunk-DRMZ5R3S.cjs +67 -0
- package/dist/{chunk-BAZMCFVL.js → chunk-DZVRH63Y.js} +1 -1
- package/dist/chunk-EI5GFTKG.js +67 -0
- package/dist/{chunk-U2ASNGO6.cjs → chunk-FXVCB6YG.cjs} +35 -35
- package/dist/{chunk-EU2ZZA6L.cjs → chunk-GHGBIAWQ.cjs} +126 -39
- package/dist/chunk-JV7DKLMX.js +1073 -0
- package/dist/{chunk-2WOGXEDX.cjs → chunk-M3RZOF3G.cjs} +1 -1
- package/dist/chunk-MFBUQC67.cjs +328 -0
- package/dist/{chunk-GSTSZPSR.js → chunk-N3SKPQEH.js} +225 -18
- package/dist/{chunk-J5VQYK7T.cjs → chunk-N5IMDAHM.cjs} +251 -44
- package/dist/{chunk-ININNHLM.js → chunk-NAHJV3O6.js} +11 -5
- package/dist/{chunk-IBXEQOGI.js → chunk-PYHB2EHE.js} +2 -324
- package/dist/chunk-QEUI6OGE.cjs +336 -0
- package/dist/{chunk-6ZSFRRJI.js → chunk-RSF6BT34.js} +1 -1
- package/dist/{chunk-JJ2H25JG.cjs → chunk-SNAFFCAX.cjs} +200 -174
- package/dist/chunk-T2HUQBRC.cjs +1073 -0
- package/dist/{chunk-M2ZVPU7L.cjs → chunk-TNLKFW7D.cjs} +23 -23
- package/dist/{chunk-KZI3YWKW.js → chunk-UXYCY3HP.js} +93 -6
- package/dist/{chunk-GSLOH2IN.cjs → chunk-VF6ODSYX.cjs} +2 -0
- package/dist/{chunk-NQUKTRKN.cjs → chunk-WZLNNGG3.cjs} +45 -45
- package/dist/{chunk-NRBGAEFI.cjs → chunk-Y3RUYOOW.cjs} +8 -330
- package/dist/{chunk-DDL3ZBHK.cjs → chunk-YJANF2BL.cjs} +86 -86
- package/dist/{chunk-TNHDCP4R.js → chunk-ZEI7ZEA4.js} +31 -5
- package/dist/commands/index.cjs +7 -323
- package/dist/commands/index.js +5 -321
- package/dist/extensions/index.cjs +4 -4
- package/dist/extensions/index.js +3 -3
- package/dist/image-editor/index.cjs +789 -789
- package/dist/image-editor/index.js +5 -5
- package/dist/index.cjs +9 -9
- package/dist/index.js +3 -3
- package/dist/paint/index.cjs +2 -2
- package/dist/paint/index.js +1 -1
- package/dist/paint/wet/world.d.cts +37 -1
- package/dist/paint/wet/world.d.ts +37 -1
- package/dist/paint-editor/brush-controls.d.cts +2 -0
- package/dist/paint-editor/brush-controls.d.ts +2 -0
- package/dist/paint-editor/brush-model.d.cts +14 -1
- package/dist/paint-editor/brush-model.d.ts +14 -1
- package/dist/paint-editor/index.cjs +343 -306
- package/dist/paint-editor/index.js +48 -11
- package/dist/paint-editor/ui.d.cts +1 -1
- package/dist/paint-editor/ui.d.ts +1 -1
- package/dist/paint-editor/wet.d.cts +8 -1
- package/dist/paint-editor/wet.d.ts +8 -1
- package/dist/persistence/index.cjs +24 -1042
- package/dist/persistence/index.js +22 -1040
- package/dist/tools/index.cjs +5 -3
- package/dist/tools/index.js +8 -6
- package/dist/vector/index.cjs +999 -999
- package/dist/vector/index.js +5 -5
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +1 -0
- package/skills/pixerate-paint-editor/SKILL.md +4 -11
- package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
- package/skills/pixerate-paint-editor/references/ghost.md +47 -0
- package/skills/pixerate-paint-watercolour/SKILL.md +1 -0
|
@@ -775,6 +775,51 @@ var BRUSH_PRESETS = [
|
|
|
775
775
|
marks: { kind: "scatter", density: 0.7, size: 0.04 },
|
|
776
776
|
dynamics: { smoothing: 0.2, pressureSize: false, pressureOpacity: true },
|
|
777
777
|
colour: { palette: ["#ef4444", "#f97316", "#facc15", "#22c55e", "#3b82f6", "#a855f7", "#111827", "#f8fafc"] }
|
|
778
|
+
},
|
|
779
|
+
// --- Ghost paint: wet paint whose colour vanishes, leaving only what it smeared ---
|
|
780
|
+
{
|
|
781
|
+
id: "ghost-wash",
|
|
782
|
+
name: "Ghost wash",
|
|
783
|
+
kind: "mark",
|
|
784
|
+
medium: "paint",
|
|
785
|
+
variety: "watercolor",
|
|
786
|
+
tip: { shape: "round", size: 32, hardness: 0.55, spacing: 0.12 },
|
|
787
|
+
dynamics: { smoothing: 0.25, pressureOpacity: true, minSize: 0.35 },
|
|
788
|
+
behaviour: { surface: "wet", wet: { water: 0.65, rewet: 0.2 } },
|
|
789
|
+
ghost: {}
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
id: "ghost-gouache",
|
|
793
|
+
name: "Ghost gouache",
|
|
794
|
+
kind: "mark",
|
|
795
|
+
medium: "paint",
|
|
796
|
+
variety: "gouache",
|
|
797
|
+
tip: { shape: "round", size: 26, hardness: 0.7 },
|
|
798
|
+
dynamics: { smoothing: 0.25, minSize: 0.5 },
|
|
799
|
+
behaviour: { surface: "wet", wet: { water: 0.35, pigment: 0.85, body: 1, rewet: 0.3 } },
|
|
800
|
+
ghost: { linger: 5, smear: 0.4 }
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
id: "ghost-oil",
|
|
804
|
+
name: "Ghost oil",
|
|
805
|
+
kind: "mark",
|
|
806
|
+
medium: "paint",
|
|
807
|
+
variety: "oil",
|
|
808
|
+
tip: { shape: "round", size: 24, hardness: 0.75, spacing: 0.08 },
|
|
809
|
+
dynamics: { smoothing: 0.25, minSize: 0.5 },
|
|
810
|
+
behaviour: { surface: "wet", wet: { water: 0.4, pigment: 0.9, body: 1, load: 0.97 } },
|
|
811
|
+
ghost: { linger: 10, smear: 0.5 }
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
id: "invisible-ink",
|
|
815
|
+
name: "Invisible ink",
|
|
816
|
+
kind: "mark",
|
|
817
|
+
medium: "paint",
|
|
818
|
+
variety: "watercolor",
|
|
819
|
+
tip: { shape: "round", size: 24, hardness: 0.65 },
|
|
820
|
+
dynamics: { smoothing: 0.3, minSize: 0.4 },
|
|
821
|
+
behaviour: { surface: "wet", wet: { water: 0.45, pigment: 0, rewet: 0.35 } },
|
|
822
|
+
ghost: { smear: 0.65 }
|
|
778
823
|
}
|
|
779
824
|
];
|
|
780
825
|
|
|
@@ -897,6 +942,13 @@ var DEFAULT_LIGHT = { amount: 0, pressure: false };
|
|
|
897
942
|
function normalizeLight(raw = {}, base = DEFAULT_LIGHT) {
|
|
898
943
|
return { amount: unit2(raw.amount, base.amount), pressure: typeof raw.pressure === "boolean" ? raw.pressure : base.pressure };
|
|
899
944
|
}
|
|
945
|
+
var DEFAULT_GHOST = { linger: 4, smear: 0.3 };
|
|
946
|
+
function normalizeGhost(raw = {}, base = DEFAULT_GHOST) {
|
|
947
|
+
return {
|
|
948
|
+
linger: range(raw.linger, 0.5, 60, base.linger),
|
|
949
|
+
smear: unit2(raw.smear, base.smear)
|
|
950
|
+
};
|
|
951
|
+
}
|
|
900
952
|
function normalizeImpasto(raw = {}, base = DEFAULT_IMPASTO) {
|
|
901
953
|
return {
|
|
902
954
|
tool: IMPASTO_TOOLS.includes(raw.tool) ? raw.tool : base.tool,
|
|
@@ -1085,6 +1137,10 @@ function normalizePaintBrush(raw = {}, base) {
|
|
|
1085
1137
|
paint = mc.mode === "off" ? paintToMultiColor(paint) ? null : paint : multiColorToPaint(mc, behavior.mixing);
|
|
1086
1138
|
}
|
|
1087
1139
|
behavior = { ...behavior, multicolor: _nullishCoalesce(paintToMultiColor(paint), () => ( { ...DEFAULT_MULTI_COLOR, colors: [] })) };
|
|
1140
|
+
const wet = normalizeWetBrush(_nullishCoalesce(raw.wet, () => ( {})), _nullishCoalesce(b.wet, () => ( DEFAULT_WET_BRUSH)));
|
|
1141
|
+
const wantsLight = typeof _optionalChain([raw, 'access', _3 => _3.light, 'optionalAccess', _4 => _4.amount]) === "number" && raw.light.amount > 0;
|
|
1142
|
+
const ghost = engine === "wet" && wet.tool === "paint" && (raw.ghost !== void 0 ? raw.ghost !== null : !wantsLight && Boolean(b.ghost)) ? normalizeGhost(_nullishCoalesce(raw.ghost, () => ( {})), _nullishCoalesce(b.ghost, () => ( DEFAULT_GHOST))) : void 0;
|
|
1143
|
+
if (ghost) behavior = { ...behavior, pickup: 0, dirty: false };
|
|
1088
1144
|
return {
|
|
1089
1145
|
id,
|
|
1090
1146
|
name: typeof raw.name === "string" && raw.name.trim() ? raw.name.trim().slice(0, 80) : b.name,
|
|
@@ -1100,12 +1156,13 @@ function normalizePaintBrush(raw = {}, base) {
|
|
|
1100
1156
|
behavior,
|
|
1101
1157
|
blender: _chunkNIBFKXMDcjs.normalizeBlender.call(void 0, _nullishCoalesce(raw.blender, () => ( {})), b.blender),
|
|
1102
1158
|
smudge: _chunkNIBFKXMDcjs.normalizeSmudge.call(void 0, _nullishCoalesce(raw.smudge, () => ( {})), b.smudge),
|
|
1103
|
-
wet
|
|
1159
|
+
wet,
|
|
1104
1160
|
impasto: normalizeImpasto(_nullishCoalesce(raw.impasto, () => ( {})), _nullishCoalesce(b.impasto, () => ( DEFAULT_IMPASTO))),
|
|
1105
1161
|
particle: normalizeParticle(_nullishCoalesce(raw.particle, () => ( {})), _nullishCoalesce(b.particle, () => ( DEFAULT_PARTICLE))),
|
|
1106
1162
|
bristle: normalizeBristle(_nullishCoalesce(raw.bristle, () => ( {})), _nullishCoalesce(b.bristle, () => ( DEFAULT_BRISTLE))),
|
|
1107
1163
|
sticker: normalizeStickerSettings(_nullishCoalesce(raw.sticker, () => ( {})), _nullishCoalesce(b.sticker, () => ( DEFAULT_STICKER))),
|
|
1108
|
-
light: normalizeLight(_nullishCoalesce(raw.light, () => ( {})), _nullishCoalesce(b.light, () => ( DEFAULT_LIGHT))),
|
|
1164
|
+
light: ghost && !wantsLight ? { ...DEFAULT_LIGHT } : normalizeLight(_nullishCoalesce(raw.light, () => ( {})), _nullishCoalesce(b.light, () => ( DEFAULT_LIGHT))),
|
|
1165
|
+
...ghost ? { ghost } : {},
|
|
1109
1166
|
stamp: readStamp(raw.stamp, _nullishCoalesce(b.stamp, () => ( null))),
|
|
1110
1167
|
spray: readSpray(raw.spray, _nullishCoalesce(b.spray, () => ( null))),
|
|
1111
1168
|
...withTipGrain(readTipGrain(raw.tipGrain, _nullishCoalesce(b.tipGrain, () => ( null)))),
|
|
@@ -1194,6 +1251,7 @@ var BRUSH_FIELDS = [
|
|
|
1194
1251
|
f("behaviour.strength", "wet.strength", ["wet"]),
|
|
1195
1252
|
// Surfaces.
|
|
1196
1253
|
...each("behaviour.wet", "wet", ["medium", "water", "pigment", "body", "rewet", "load", "thinner"], ["wet"]),
|
|
1254
|
+
...each("ghost", "ghost", ["linger", "smear"], ["wet"]),
|
|
1197
1255
|
f("behaviour.thick.applicator", "impasto.tool", ["impasto"]),
|
|
1198
1256
|
...each("behaviour.thick", "impasto", ["thickness", "gloss", "metallic", "load", "thinner", "drag", "rim", "clarity"], ["impasto"]),
|
|
1199
1257
|
// Marks.
|
|
@@ -1232,13 +1290,13 @@ function setPath(o, path, value) {
|
|
|
1232
1290
|
var copy = (v) => v !== null && typeof v === "object" ? JSON.parse(JSON.stringify(v)) : v;
|
|
1233
1291
|
function resolveEngine(brush) {
|
|
1234
1292
|
if (brush.kind === "tool") return brush.tool === "eraser" || brush.tool === "blender" || brush.tool === "smudge" ? brush.tool : "wet";
|
|
1235
|
-
if (_optionalChain([brush, 'access',
|
|
1236
|
-
if (_optionalChain([brush, 'access',
|
|
1293
|
+
if (_optionalChain([brush, 'access', _5 => _5.marks, 'optionalAccess', _6 => _6.kind]) === "particles") return "particle";
|
|
1294
|
+
if (_optionalChain([brush, 'access', _7 => _7.marks, 'optionalAccess', _8 => _8.kind]) === "objects") return "sticker";
|
|
1237
1295
|
if (brush.tip.shape === "bristle") return "bristle";
|
|
1238
|
-
const surface = _optionalChain([brush, 'access',
|
|
1296
|
+
const surface = _optionalChain([brush, 'access', _9 => _9.behaviour, 'optionalAccess', _10 => _10.surface]);
|
|
1239
1297
|
if (surface === "thick") return "impasto";
|
|
1240
1298
|
if (surface === "wet") return "wet";
|
|
1241
|
-
if (_optionalChain([brush, 'access',
|
|
1299
|
+
if (_optionalChain([brush, 'access', _11 => _11.behaviour, 'optionalAccess', _12 => _12.exchange, 'optionalAccess', _13 => _13.reservoir])) return "mixer";
|
|
1242
1300
|
return "dab";
|
|
1243
1301
|
}
|
|
1244
1302
|
var VARIETY_CATEGORY = {
|
|
@@ -1254,11 +1312,11 @@ var VARIETY_CATEGORY = {
|
|
|
1254
1312
|
};
|
|
1255
1313
|
var MEDIUM_CATEGORY = { paint: "paint", ink: "ink", dry: "pencil", spray: "airbrush" };
|
|
1256
1314
|
function resolveWetMedium(brush) {
|
|
1257
|
-
return _nullishCoalesce(_optionalChain([brush, 'access',
|
|
1315
|
+
return _nullishCoalesce(_optionalChain([brush, 'access', _14 => _14.behaviour, 'optionalAccess', _15 => _15.wet, 'optionalAccess', _16 => _16.medium]), () => ( (WET_MEDIA.includes(brush.variety) ? brush.variety : void 0)));
|
|
1258
1316
|
}
|
|
1259
1317
|
function resolveCategory(brush, engine = resolveEngine(brush)) {
|
|
1260
1318
|
if (brush.kind === "tool") return brush.tool === "eraser" || brush.tool === "blender" || brush.tool === "smudge" ? brush.tool : "wet-tool";
|
|
1261
|
-
if ((_nullishCoalesce(_optionalChain([brush, 'access',
|
|
1319
|
+
if ((_nullishCoalesce(_optionalChain([brush, 'access', _17 => _17.light, 'optionalAccess', _18 => _18.amount]), () => ( 0))) > 0) return "light";
|
|
1262
1320
|
switch (engine) {
|
|
1263
1321
|
case "particle":
|
|
1264
1322
|
return "procedural";
|
|
@@ -1280,18 +1338,19 @@ function resolveBrush(brush, options = {}) {
|
|
|
1280
1338
|
const engine = resolveEngine(brush);
|
|
1281
1339
|
const input = { id: brush.id, name: brush.name, category: resolveCategory(brush, engine), engine };
|
|
1282
1340
|
for (const field of BRUSH_FIELDS) {
|
|
1283
|
-
if (!field.engines.includes(engine) || field.shapes && !field.shapes.includes(brush.tip.shape) || field.marks && !field.marks.includes(_nullishCoalesce(_optionalChain([brush, 'access',
|
|
1341
|
+
if (!field.engines.includes(engine) || field.shapes && !field.shapes.includes(brush.tip.shape) || field.marks && !field.marks.includes(_nullishCoalesce(_optionalChain([brush, 'access', _19 => _19.marks, 'optionalAccess', _20 => _20.kind]), () => ( "continuous")))) continue;
|
|
1284
1342
|
const v = getPath(brush, field.facet);
|
|
1285
1343
|
if (v !== void 0) setPath(input, field.engine, field.map ? field.map.toEngine(v) : copy(v));
|
|
1286
1344
|
}
|
|
1287
|
-
if (engine === "dab" && _optionalChain([brush, 'access',
|
|
1345
|
+
if (engine === "dab" && _optionalChain([brush, 'access', _21 => _21.marks, 'optionalAccess', _22 => _22.kind]) === "scatter") input.spray = { ..._nullishCoalesce(input.spray, () => ( {})) };
|
|
1288
1346
|
if (engine === "wet") {
|
|
1289
1347
|
setPath(input, "wet.tool", brush.kind === "tool" ? WET_TOOL_OF[brush.tool] : "paint");
|
|
1290
1348
|
const medium = resolveWetMedium(brush);
|
|
1291
1349
|
if (medium) setPath(input, "wet.medium", medium);
|
|
1350
|
+
if (brush.kind !== "tool" && brush.ghost) input.ghost = { ..._nullishCoalesce(input.ghost, () => ( {})) };
|
|
1292
1351
|
}
|
|
1293
1352
|
if (engine === "blender" || engine === "smudge") input.loadsColor = false;
|
|
1294
|
-
const paint = _optionalChain([brush, 'access',
|
|
1353
|
+
const paint = _optionalChain([brush, 'access', _23 => _23.colour, 'optionalAccess', _24 => _24.default]);
|
|
1295
1354
|
if (paint && typeof paint === "object" && "type" in paint && paint.type === "gradient") input.paint = copy(paint);
|
|
1296
1355
|
return normalizePaintBrush({ ...input, ...options.builtin ? { builtin: true } : {} });
|
|
1297
1356
|
}
|
|
@@ -1354,7 +1413,7 @@ function skeleton(b) {
|
|
|
1354
1413
|
}
|
|
1355
1414
|
switch (b.engine) {
|
|
1356
1415
|
case "wet":
|
|
1357
|
-
return { ...brush, medium: "paint", variety: b.wet.medium, behaviour: { surface: "wet" } };
|
|
1416
|
+
return { ...brush, medium: "paint", variety: b.wet.medium, behaviour: { surface: "wet" }, ...b.ghost ? { ghost: {} } : {} };
|
|
1358
1417
|
case "impasto":
|
|
1359
1418
|
return { ...brush, medium: "paint", behaviour: { surface: "thick" } };
|
|
1360
1419
|
case "mixer":
|
|
@@ -1371,13 +1430,13 @@ function skeleton(b) {
|
|
|
1371
1430
|
}
|
|
1372
1431
|
}
|
|
1373
1432
|
}
|
|
1374
|
-
var ORDER = ["id", "name", "description", "tags", "kind", "medium", "variety", "tool", "tip", "marks", "dynamics", "behaviour", "light", "motion", "colour"];
|
|
1433
|
+
var ORDER = ["id", "name", "description", "tags", "kind", "medium", "variety", "tool", "tip", "marks", "dynamics", "behaviour", "light", "ghost", "motion", "colour"];
|
|
1375
1434
|
function migrateBrushV1(raw) {
|
|
1376
1435
|
const b = normalizePaintBrush(raw);
|
|
1377
1436
|
const brush = skeleton(b);
|
|
1378
1437
|
const defaults = resolveBrush(brush);
|
|
1379
1438
|
for (const field of BRUSH_FIELDS) {
|
|
1380
|
-
if (!field.engines.includes(b.engine) || field.shapes && !field.shapes.includes(brush.tip.shape) || field.marks && !field.marks.includes(_nullishCoalesce(_optionalChain([brush, 'access',
|
|
1439
|
+
if (!field.engines.includes(b.engine) || field.shapes && !field.shapes.includes(brush.tip.shape) || field.marks && !field.marks.includes(_nullishCoalesce(_optionalChain([brush, 'access', _25 => _25.marks, 'optionalAccess', _26 => _26.kind]), () => ( "continuous")))) continue;
|
|
1381
1440
|
const v = getPath(b, field.engine);
|
|
1382
1441
|
if (!equal(v, getPath(defaults, field.engine))) setPath(brush, field.facet, field.map ? field.map.toFacet(v) : copy2(v));
|
|
1383
1442
|
}
|
|
@@ -1586,6 +1645,10 @@ var LIGHT = object("Light the brush gives off with its colour (glow and spill).
|
|
|
1586
1645
|
}),
|
|
1587
1646
|
glow: bool("Suggest a glow layer effect for the layer (glow stays a layer effect).")
|
|
1588
1647
|
});
|
|
1648
|
+
var GHOST = object('Ghost paint: wet paint that flows and mixes visibly while wet, then fades away without leaving its colour, keeping only the smear it made in the paint it touched (needs behaviour.surface "wet").', {
|
|
1649
|
+
linger: num(0.5, 60, "Seconds of simulated time before the ghost paint has fully faded (default 4)."),
|
|
1650
|
+
smear: unit3("How much the ghost paint drags and lifts the paint it passes through: 0 none .. 1 full (default 0.3).")
|
|
1651
|
+
});
|
|
1589
1652
|
var MOTION = object("Animation after painting.", {
|
|
1590
1653
|
live: bool("Effect paint keeps playing on stroke layers (default false)."),
|
|
1591
1654
|
fps: int(1, 60, "Suggested playback rate in frames per second."),
|
|
@@ -1649,6 +1712,7 @@ var BRUSH_JSON_SCHEMA = object(
|
|
|
1649
1712
|
dynamics: DYNAMICS,
|
|
1650
1713
|
behaviour: BEHAVIOUR,
|
|
1651
1714
|
light: LIGHT,
|
|
1715
|
+
ghost: GHOST,
|
|
1652
1716
|
motion: MOTION,
|
|
1653
1717
|
colour: COLOUR
|
|
1654
1718
|
},
|
|
@@ -1661,6 +1725,7 @@ var BRUSH_FACET_SCHEMAS = {
|
|
|
1661
1725
|
dynamics: DYNAMICS,
|
|
1662
1726
|
behaviour: BEHAVIOUR,
|
|
1663
1727
|
light: LIGHT,
|
|
1728
|
+
ghost: GHOST,
|
|
1664
1729
|
motion: MOTION,
|
|
1665
1730
|
colour: COLOUR,
|
|
1666
1731
|
paint: PAINT
|
|
@@ -1866,7 +1931,7 @@ function readObject(value, schema, path, problems) {
|
|
|
1866
1931
|
const out = {};
|
|
1867
1932
|
for (const [key, v] of Object.entries(value)) {
|
|
1868
1933
|
if (v === void 0) continue;
|
|
1869
|
-
const child = _optionalChain([schema, 'access',
|
|
1934
|
+
const child = _optionalChain([schema, 'access', _27 => _27.properties, 'optionalAccess', _28 => _28[key]]);
|
|
1870
1935
|
if (!child) {
|
|
1871
1936
|
problems.push(`${path}.${key} is not a brush field; dropped.`);
|
|
1872
1937
|
continue;
|
|
@@ -1906,8 +1971,8 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
1906
1971
|
const out = readObject(rest, BRUSH_JSON_SCHEMA, "brush", problems);
|
|
1907
1972
|
const brush = { id: raw.id, name, ...out, kind, ...tool ? { tool } : {}, tip: _nullishCoalesce(out.tip, () => ( { shape: "round" })) };
|
|
1908
1973
|
const ordered = () => {
|
|
1909
|
-
const { id, name: n, description, tags, kind: k, medium, variety, tool: t, tip, marks, dynamics, behaviour, light, motion, colour } = brush;
|
|
1910
|
-
const all = { id, name: n, description, tags, kind: k, medium, variety, tool: t, tip, marks, dynamics, behaviour, light, motion, colour };
|
|
1974
|
+
const { id, name: n, description, tags, kind: k, medium, variety, tool: t, tip, marks, dynamics, behaviour, light, ghost, motion, colour } = brush;
|
|
1975
|
+
const all = { id, name: n, description, tags, kind: k, medium, variety, tool: t, tip, marks, dynamics, behaviour, light, ghost, motion, colour };
|
|
1911
1976
|
return Object.fromEntries(Object.entries(all).filter(([, v]) => v !== void 0));
|
|
1912
1977
|
};
|
|
1913
1978
|
if (!out.tip) problems.push("tip is missing; a round tip is used.");
|
|
@@ -1956,15 +2021,15 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
1956
2021
|
delete brush.marks;
|
|
1957
2022
|
}
|
|
1958
2023
|
}
|
|
1959
|
-
if (_optionalChain([brush, 'access',
|
|
1960
|
-
const surface = _optionalChain([brush, 'access',
|
|
1961
|
-
const why = brush.tip.shape === "bristle" ? "bristle tips lay their own marks" : surface === "wet" || surface === "thick" ? `${surface} paint is not sprayed` : _optionalChain([brush, 'access',
|
|
2024
|
+
if (_optionalChain([brush, 'access', _29 => _29.marks, 'optionalAccess', _30 => _30.kind]) === "scatter") {
|
|
2025
|
+
const surface = _optionalChain([brush, 'access', _31 => _31.behaviour, 'optionalAccess', _32 => _32.surface]);
|
|
2026
|
+
const why = brush.tip.shape === "bristle" ? "bristle tips lay their own marks" : surface === "wet" || surface === "thick" ? `${surface} paint is not sprayed` : _optionalChain([brush, 'access', _33 => _33.behaviour, 'optionalAccess', _34 => _34.exchange, 'optionalAccess', _35 => _35.reservoir]) ? "the Mixer Brush is not sprayed" : null;
|
|
1962
2027
|
if (why) {
|
|
1963
2028
|
drop("marks", why);
|
|
1964
2029
|
delete brush.marks;
|
|
1965
2030
|
}
|
|
1966
2031
|
}
|
|
1967
|
-
if (_optionalChain([brush, 'access',
|
|
2032
|
+
if (_optionalChain([brush, 'access', _36 => _36.marks, 'optionalAccess', _37 => _37.kind]) === "objects" && brush.tip.shape !== "stamp") {
|
|
1968
2033
|
problems.push("marks objects lay stamps: tip.shape set to stamp.");
|
|
1969
2034
|
brush.tip.shape = "stamp";
|
|
1970
2035
|
}
|
|
@@ -1978,7 +2043,7 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
1978
2043
|
}
|
|
1979
2044
|
if (brush.tip.stamps) {
|
|
1980
2045
|
let stamps = brush.tip.stamps.map((s) => _chunkRDFHWAHLcjs.normalizeStickerRef.call(void 0, s));
|
|
1981
|
-
if (_optionalChain([brush, 'access',
|
|
2046
|
+
if (_optionalChain([brush, 'access', _38 => _38.marks, 'optionalAccess', _39 => _39.kind]) === "objects" && stamps.some(isBrushSourceRef)) {
|
|
1982
2047
|
problems.push("tip.stamps: image sources (source:\u2026) dropped: objects marks lay stickers; use continuous, scatter or particles marks for an image tip.");
|
|
1983
2048
|
stamps = stamps.filter((s) => !isBrushSourceRef(s));
|
|
1984
2049
|
}
|
|
@@ -1989,8 +2054,8 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
1989
2054
|
}
|
|
1990
2055
|
}
|
|
1991
2056
|
if (brush.tip.grain) {
|
|
1992
|
-
const surface = _optionalChain([brush, 'access',
|
|
1993
|
-
const marks = _optionalChain([brush, 'access',
|
|
2057
|
+
const surface = _optionalChain([brush, 'access', _40 => _40.behaviour, 'optionalAccess', _41 => _41.surface]);
|
|
2058
|
+
const marks = _optionalChain([brush, 'access', _42 => _42.marks, 'optionalAccess', _43 => _43.kind]);
|
|
1994
2059
|
const why = !brush.tip.grain.source ? "it needs a source (a grain pattern or source:<id>)" : brush.tip.shape === "bristle" ? "bristle tips lay their own marks" : marks === "particles" || marks === "objects" ? `${marks} marks are not dabs` : surface === "wet" || surface === "thick" ? `${surface} paint lays its own texture` : kind === "tool" && WET_BRUSH_TOOLS.includes(brush.tool) ? "the wet tools work on the wet layer" : null;
|
|
1995
2060
|
if (why) {
|
|
1996
2061
|
drop("tip.grain", why);
|
|
@@ -2027,11 +2092,26 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
2027
2092
|
if (b.exchange && kind === "tool" && !wetTool) {
|
|
2028
2093
|
drop("behaviour.exchange", `the ${brush.tool} does not pick paint up`);
|
|
2029
2094
|
delete b.exchange;
|
|
2030
|
-
} else if (b.exchange && (_optionalChain([brush, 'access',
|
|
2095
|
+
} else if (b.exchange && (_optionalChain([brush, 'access', _44 => _44.marks, 'optionalAccess', _45 => _45.kind]) === "particles" || _optionalChain([brush, 'access', _46 => _46.marks, 'optionalAccess', _47 => _47.kind]) === "objects" || brush.tip.shape === "bristle")) {
|
|
2031
2096
|
drop("behaviour.exchange", "particle, object and bristle marks do not pick paint up");
|
|
2032
2097
|
delete b.exchange;
|
|
2033
2098
|
}
|
|
2034
2099
|
}
|
|
2100
|
+
if (brush.ghost) {
|
|
2101
|
+
if (kind === "tool" || _optionalChain([brush, 'access', _48 => _48.behaviour, 'optionalAccess', _49 => _49.surface]) !== "wet") {
|
|
2102
|
+
drop("ghost", "it needs a mark brush with behaviour.surface wet");
|
|
2103
|
+
delete brush.ghost;
|
|
2104
|
+
} else {
|
|
2105
|
+
if (brush.light) {
|
|
2106
|
+
drop("light", "ghost paint uses the wet light channel as its tracer");
|
|
2107
|
+
delete brush.light;
|
|
2108
|
+
}
|
|
2109
|
+
if (_optionalChain([brush, 'access', _50 => _50.behaviour, 'optionalAccess', _51 => _51.exchange])) {
|
|
2110
|
+
drop("behaviour.exchange", "ghost paint does not pick paint up");
|
|
2111
|
+
delete brush.behaviour.exchange;
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2035
2115
|
return ordered();
|
|
2036
2116
|
}
|
|
2037
2117
|
|
|
@@ -2121,15 +2201,16 @@ function checkBrush(brush, profile) {
|
|
|
2121
2201
|
const image = brush.tip.shape === "stamp" && (_nullishCoalesce(brush.tip.stamps, () => ( []))).some(isBrushSourceRef);
|
|
2122
2202
|
add("tip.shape", "error", `${host} can't lay a ${image ? "stamp tip (image tips are stamps)" : `${brush.tip.shape} tip`}.`, `Set tip.shape to one of: ${list(profile.tipShapes)}.`);
|
|
2123
2203
|
}
|
|
2124
|
-
const marks = _nullishCoalesce(_optionalChain([brush, 'access',
|
|
2204
|
+
const marks = _nullishCoalesce(_optionalChain([brush, 'access', _52 => _52.marks, 'optionalAccess', _53 => _53.kind]), () => ( "continuous"));
|
|
2125
2205
|
if (!profile.marks.includes(marks)) add("marks", "error", `${host} can't lay ${marks} marks.`, `Use marks ${list(profile.marks)} (remove marks for continuous dabs).`);
|
|
2126
|
-
const surface = _nullishCoalesce(_optionalChain([brush, 'access',
|
|
2206
|
+
const surface = _nullishCoalesce(_optionalChain([brush, 'access', _54 => _54.behaviour, 'optionalAccess', _55 => _55.surface]), () => ( "dry"));
|
|
2127
2207
|
if (brush.kind === "mark" && !profile.surfaces.includes(surface)) add("behaviour.surface", "error", `${host} has no ${surface} surface.`, `Set behaviour.surface to ${list(profile.surfaces)}.`);
|
|
2128
|
-
const ex = _optionalChain([brush, 'access',
|
|
2129
|
-
feature(profile.reservoir, !!_optionalChain([ex, 'optionalAccess',
|
|
2130
|
-
feature(profile.exchange, !_optionalChain([ex, 'optionalAccess',
|
|
2131
|
-
feature(profile.grain, nonZero(_optionalChain([brush, 'access',
|
|
2132
|
-
feature(profile.light, nonZero(_optionalChain([brush, 'access',
|
|
2208
|
+
const ex = _optionalChain([brush, 'access', _56 => _56.behaviour, 'optionalAccess', _57 => _57.exchange]);
|
|
2209
|
+
feature(profile.reservoir, !!_optionalChain([ex, 'optionalAccess', _58 => _58.reservoir]), "behaviour.exchange.reservoir", "a Mixer Brush reservoir", "Remove behaviour.exchange.reservoir.");
|
|
2210
|
+
feature(profile.exchange, !_optionalChain([ex, 'optionalAccess', _59 => _59.reservoir]) && (nonZero(_optionalChain([ex, 'optionalAccess', _60 => _60.pickup])) || !!_optionalChain([ex, 'optionalAccess', _61 => _61.dirty])), "behaviour.exchange", "picking paint up", "Remove behaviour.exchange.");
|
|
2211
|
+
feature(profile.grain, nonZero(_optionalChain([brush, 'access', _62 => _62.behaviour, 'optionalAccess', _63 => _63.grain])), "behaviour.grain", "paper grain", "Set behaviour.grain to 0.");
|
|
2212
|
+
feature(profile.light, nonZero(_optionalChain([brush, 'access', _64 => _64.light, 'optionalAccess', _65 => _65.amount])), "light", "light paint (glow and spill)", "Remove light (or set light.amount to 0).");
|
|
2213
|
+
feature(profile.surfaces.includes("wet") && profile.light === "full" ? "full" : "none", !!brush.ghost, "ghost", "ghost paint", "Remove ghost.");
|
|
2133
2214
|
const m = brush.motion;
|
|
2134
2215
|
feature(profile.motion, !!m && (!!m.live || nonZero(m.waveSpeed) || m.fps !== void 0), "motion", "animation", "Remove motion.");
|
|
2135
2216
|
const d = _nullishCoalesce(brush.dynamics, () => ( {}));
|
|
@@ -2138,16 +2219,16 @@ function checkBrush(brush, profile) {
|
|
|
2138
2219
|
feature(profile.velocity, nonZero(d.velocitySize) || nonZero(d.velocityOpacity), "dynamics.velocity", "velocity dynamics (its strokes carry no timing)", "Set dynamics.velocitySize and velocityOpacity to 0.");
|
|
2139
2220
|
feature(profile.tilt, nonZero(d.tiltSize) || nonZero(d.tiltRoundness) || nonZero(d.tiltOpacity), "dynamics.tilt", "tilt dynamics", "Set dynamics.tiltSize, tiltRoundness and tiltOpacity to 0.");
|
|
2140
2221
|
const colour = brush.colour;
|
|
2141
|
-
if (_optionalChain([colour, 'optionalAccess',
|
|
2222
|
+
if (_optionalChain([colour, 'optionalAccess', _66 => _66.default]) !== void 0) {
|
|
2142
2223
|
const kind = brushColourKind(colour.default);
|
|
2143
2224
|
if (!profile.colours.includes(kind)) add("colour.default", "error", `${host} can't paint ${kind} colours.`, `Use a ${list(profile.colours)} colour, or remove colour.default.`);
|
|
2144
2225
|
}
|
|
2145
|
-
const foreign = [...new Set((_nullishCoalesce(_optionalChain([colour, 'optionalAccess',
|
|
2226
|
+
const foreign = [...new Set((_nullishCoalesce(_optionalChain([colour, 'optionalAccess', _67 => _67.palette]), () => ( []))).map(brushColourKind).filter((k) => !profile.colours.includes(k)))];
|
|
2146
2227
|
if (foreign.length) add("colour.palette", "warning", `${host} skips the palette's ${list(foreign)} colours.`, `Nothing to do; or keep to ${list(profile.colours)} colours.`);
|
|
2147
2228
|
return { ok: !issues.some((i) => i.severity === "error"), issues };
|
|
2148
2229
|
}
|
|
2149
2230
|
function withKeptIssues(check, before) {
|
|
2150
|
-
const had = new Set((_nullishCoalesce(_optionalChain([before, 'optionalAccess',
|
|
2231
|
+
const had = new Set((_nullishCoalesce(_optionalChain([before, 'optionalAccess', _68 => _68.issues]), () => ( []))).filter((i) => i.severity === "error").map((i) => i.facet));
|
|
2151
2232
|
const kept = check.issues.filter((i) => i.severity === "error" && had.has(i.facet));
|
|
2152
2233
|
const issues = check.issues.filter((i) => !kept.includes(i));
|
|
2153
2234
|
return { ok: !issues.some((i) => i.severity === "error"), issues, kept };
|
|
@@ -2180,6 +2261,10 @@ function degrade(brush, profile, options = {}) {
|
|
|
2180
2261
|
delete b.behaviour.surface;
|
|
2181
2262
|
delete b.behaviour.wet;
|
|
2182
2263
|
delete b.behaviour.thick;
|
|
2264
|
+
delete b.ghost;
|
|
2265
|
+
break;
|
|
2266
|
+
case "ghost":
|
|
2267
|
+
delete b.ghost;
|
|
2183
2268
|
break;
|
|
2184
2269
|
case "behaviour.exchange.reservoir":
|
|
2185
2270
|
delete b.behaviour.exchange.reservoir;
|
|
@@ -2223,7 +2308,7 @@ function degrade(brush, profile, options = {}) {
|
|
|
2223
2308
|
}
|
|
2224
2309
|
dropped.push(issue);
|
|
2225
2310
|
}
|
|
2226
|
-
if (_optionalChain([b, 'access',
|
|
2311
|
+
if (_optionalChain([b, 'access', _69 => _69.behaviour, 'optionalAccess', _70 => _70.exchange]) && !Object.keys(b.behaviour.exchange).length) delete b.behaviour.exchange;
|
|
2227
2312
|
if (b.colour && !Object.keys(b.colour).length) delete b.colour;
|
|
2228
2313
|
const after = checkBrush(b, profile).issues.filter((i) => i.severity === "error");
|
|
2229
2314
|
return { brush: b, dropped, issues: after };
|
|
@@ -2267,7 +2352,7 @@ function parseBrushLibrary2(raw, problems = []) {
|
|
|
2267
2352
|
if (file && file.version !== void 0 && file.version !== 1 && file.version !== 2) {
|
|
2268
2353
|
throw new BrushLibraryError("invalid", `Brush library version ${JSON.stringify(file.version)} is not supported; this library reads versions 1 and 2.`);
|
|
2269
2354
|
}
|
|
2270
|
-
const v1File = _optionalChain([file, 'optionalAccess',
|
|
2355
|
+
const v1File = _optionalChain([file, 'optionalAccess', _71 => _71.version]) === 1;
|
|
2271
2356
|
const out = [];
|
|
2272
2357
|
items.forEach((item, i) => {
|
|
2273
2358
|
const at = `brushes[${i}]`;
|
|
@@ -2528,7 +2613,7 @@ function snapshotBrushLibrary(library, onChange) {
|
|
|
2528
2613
|
(list2) => {
|
|
2529
2614
|
entries = list2;
|
|
2530
2615
|
user = list2.filter((e) => !e.builtin).map((e) => e.brush);
|
|
2531
|
-
_optionalChain([onChange, 'optionalCall',
|
|
2616
|
+
_optionalChain([onChange, 'optionalCall', _72 => _72()]);
|
|
2532
2617
|
},
|
|
2533
2618
|
() => void 0
|
|
2534
2619
|
);
|
|
@@ -2659,4 +2744,6 @@ function snapshotBrushLibrary(library, onChange) {
|
|
|
2659
2744
|
|
|
2660
2745
|
|
|
2661
2746
|
|
|
2662
|
-
|
|
2747
|
+
|
|
2748
|
+
|
|
2749
|
+
exports.BRUSH_PRESETS = BRUSH_PRESETS; exports.MAX_STICKER_STAMPS = MAX_STICKER_STAMPS; exports.DEFAULT_STICKER = DEFAULT_STICKER; exports.normalizeStickerSettings = normalizeStickerSettings; exports.PARTICLE_KINDS = PARTICLE_KINDS; exports.PARTICLE_RENDERS = PARTICLE_RENDERS; exports.RIBBON_PAIRS = RIBBON_PAIRS; exports.DOT_TEXTURE_ORDERS = DOT_TEXTURE_ORDERS; exports.DOT_ROTATIONS = DOT_ROTATIONS; exports.MAX_DOT_TEXTURES = MAX_DOT_TEXTURES; exports.DEFAULT_PARTICLE = DEFAULT_PARTICLE; exports.normalizeParticle = normalizeParticle; exports.DEFAULT_BRISTLE = DEFAULT_BRISTLE; exports.normalizeBristle = normalizeBristle; exports.PAINT_BRUSH_ENGINES = PAINT_BRUSH_ENGINES; exports.PAINT_BRUSH_CATEGORIES = PAINT_BRUSH_CATEGORIES; exports.WET_TOOLS = WET_TOOLS; exports.WET_MEDIA = WET_MEDIA; exports.DEFAULT_WET_BRUSH = DEFAULT_WET_BRUSH; exports.normalizeWetBrush = normalizeWetBrush; exports.IMPASTO_TOOLS = IMPASTO_TOOLS; exports.DEFAULT_IMPASTO = DEFAULT_IMPASTO; exports.DEFAULT_LIGHT = DEFAULT_LIGHT; exports.normalizeLight = normalizeLight; exports.DEFAULT_GHOST = DEFAULT_GHOST; exports.normalizeGhost = normalizeGhost; exports.normalizeImpasto = normalizeImpasto; exports.MULTI_COLOR_MODES = MULTI_COLOR_MODES; exports.DEFAULT_MULTI_COLOR = DEFAULT_MULTI_COLOR; exports.DEFAULT_BEHAVIOR = DEFAULT_BEHAVIOR; exports.BRUSH_ROTATIONS = BRUSH_ROTATIONS; exports.DAB_FLIPS = DAB_FLIPS; exports.TIP_GRAIN_MODES = TIP_GRAIN_MODES; exports.DEFAULT_TIP_GRAIN = DEFAULT_TIP_GRAIN; exports.DEFAULT_DYNAMICS = DEFAULT_DYNAMICS; exports.normalizeDynamics = normalizeDynamics; exports.BRUSH_ID = BRUSH_ID; exports.normalizeMultiColor = normalizeMultiColor; exports.normalizeBehavior = normalizeBehavior; exports.DEFAULT_SPRAY = DEFAULT_SPRAY; exports.isWetCapable = isWetCapable; exports.isWetBrush = isWetBrush; exports.usesPaintExchange = usesPaintExchange; exports.brushTakesPaint = brushTakesPaint; exports.paintToMultiColor = paintToMultiColor; exports.multiColorToPaint = multiColorToPaint; exports.normalizePaintBrush = normalizePaintBrush; exports.BRUSH_FIELDS = BRUSH_FIELDS; exports.getPath = getPath; exports.setPath = setPath; exports.resolveEngine = resolveEngine; exports.resolveWetMedium = resolveWetMedium; exports.resolveCategory = resolveCategory; exports.resolveBrush = resolveBrush; exports.BUILTIN_BRUSHES = BUILTIN_BRUSHES; exports.DEFAULT_BRUSH_ID = DEFAULT_BRUSH_ID; exports.brushToJSON = brushToJSON; exports.parseBrushLibrary = parseBrushLibrary; exports.migrateBrushV1 = migrateBrushV1; exports.BRUSH_KINDS = BRUSH_KINDS; exports.BRUSH_MEDIA = BRUSH_MEDIA; exports.BRUSH_TOOLS = BRUSH_TOOLS; exports.BRUSH_TIP_SHAPES = BRUSH_TIP_SHAPES; exports.BRUSH_MARKS_KINDS = BRUSH_MARKS_KINDS; exports.BRUSH_SURFACES = BRUSH_SURFACES; exports.BRUSH_GRAIN_MODES = BRUSH_GRAIN_MODES; exports.BRUSH_FLIPS = BRUSH_FLIPS; exports.MAX_BRUSH_PALETTE = MAX_BRUSH_PALETTE; exports.BRUSH_WORD = BRUSH_WORD; exports.TIP_GRAIN_PATTERNS = TIP_GRAIN_PATTERNS; exports.BRUSH_GRAIN_SOURCE_PATTERN = BRUSH_GRAIN_SOURCE_PATTERN; exports.BRUSH_JSON_SCHEMA = BRUSH_JSON_SCHEMA; exports.BRUSH_FACET_SCHEMAS = BRUSH_FACET_SCHEMAS; exports.BRUSH_SOURCE_PROVIDER = BRUSH_SOURCE_PROVIDER; exports.MAX_BRUSH_SOURCE_SIZE = MAX_BRUSH_SOURCE_SIZE; exports.MAX_BRUSH_SOURCE_INPUT_PIXELS = MAX_BRUSH_SOURCE_INPUT_PIXELS; exports.MAX_BRUSH_SOURCES = MAX_BRUSH_SOURCES; exports.BRUSH_SOURCE_CHANNELS = BRUSH_SOURCE_CHANNELS; exports.BrushSourceError = BrushSourceError; exports.brushSourceRef = brushSourceRef; exports.isBrushSourceRef = isBrushSourceRef; exports.brushSourceIdOf = brushSourceIdOf; exports.brushSourceIds = brushSourceIds; exports.summarizeBrushSource = summarizeBrushSource; exports.brushSourceIdFromName = brushSourceIdFromName; exports.brushSourceFromMask = brushSourceFromMask; exports.makeBrushSource = makeBrushSource; exports.readBrushSource = readBrushSource; exports.decodeBrushSource = decodeBrushSource; exports.WET_BRUSH_TOOLS = WET_BRUSH_TOOLS; exports.normalizeBrushSpec = normalizeBrushSpec; exports.PAINT_PROFILE = PAINT_PROFILE; exports.IMAGE_PROFILE = IMAGE_PROFILE; exports.CANVAS_PROFILE = CANVAS_PROFILE; exports.VECTOR_PROFILE = VECTOR_PROFILE; exports.BRUSH_HOST_PROFILES = BRUSH_HOST_PROFILES; exports.brushColourKind = brushColourKind; exports.checkBrush = checkBrush; exports.withKeptIssues = withKeptIssues; exports.checkBrushEdit = checkBrushEdit; exports.listPresets = listPresets; exports.degrade = degrade; exports.BrushLibraryError = BrushLibraryError; exports.isBrushLibrary = isBrushLibrary; exports.parseBrushLibrarySources = parseBrushLibrarySources; exports.parseBrushLibrary2 = parseBrushLibrary2; exports.createBrushLibrary = createBrushLibrary; exports.closest = closest; exports.snapshotBrushLibrary = snapshotBrushLibrary;
|