@pixerate/editor 0.256.0 → 0.258.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/agent/index.cjs +40 -38
- package/dist/agent/index.js +9 -7
- package/dist/animation/index.cjs +4 -2
- package/dist/animation/index.js +4 -2
- package/dist/animation-editor/index.cjs +63 -61
- package/dist/animation-editor/index.js +7 -5
- package/dist/brushes/colour.d.cts +11 -0
- package/dist/brushes/colour.d.ts +11 -0
- package/dist/brushes/index.cjs +51 -30
- package/dist/brushes/index.d.cts +1 -0
- package/dist/brushes/index.d.ts +1 -0
- package/dist/brushes/index.js +25 -4
- package/dist/brushes/resolve.d.cts +2 -0
- package/dist/brushes/resolve.d.ts +2 -0
- package/dist/brushes/schema.d.cts +1 -0
- package/dist/brushes/schema.d.ts +1 -0
- package/dist/brushes/tools.d.cts +7 -0
- package/dist/brushes/tools.d.ts +7 -0
- package/dist/brushes/types.d.cts +10 -2
- package/dist/brushes/types.d.ts +10 -2
- package/dist/brushes/ui.d.cts +14 -3
- package/dist/brushes/ui.d.ts +14 -3
- package/dist/{brushstrokeRender-HCOQUSWW.js → brushstrokeRender-JI4W6F2G.js} +2 -2
- package/dist/{brushstrokeRender-ZZOXI5O5.cjs → brushstrokeRender-MQ6PSDM5.cjs} +11 -11
- package/dist/canvas/index.cjs +20 -18
- package/dist/canvas/index.js +7 -5
- package/dist/chart/index.cjs +159 -157
- package/dist/chart/index.js +9 -7
- package/dist/{chunk-7272D3K2.js → chunk-2EUW2XZX.js} +27 -276
- package/dist/{chunk-L6Y7TSQ4.js → chunk-2VJ6OVJV.js} +1 -1
- package/dist/{chunk-6ZZKRH7R.js → chunk-47V3WXDG.js} +2 -2
- package/dist/{chunk-H7ET2ISK.cjs → chunk-4IMD2TLY.cjs} +52 -52
- package/dist/{chunk-VUKUTT2W.js → chunk-4M4E3N6X.js} +1 -1
- package/dist/{chunk-TBAVCLEQ.cjs → chunk-5Q5MLXAD.cjs} +23 -23
- package/dist/{chunk-MONXNVZK.js → chunk-6I23ZCGK.js} +5 -3
- package/dist/{chunk-GOBOCZZI.js → chunk-6NQPKNUZ.js} +1 -1
- package/dist/{chunk-WYGSR3IJ.js → chunk-AORZ5M5C.js} +1 -1
- package/dist/chunk-AVTPZO4Z.cjs +142 -0
- package/dist/{chunk-WKMUBATU.js → chunk-C2WEIEUB.js} +1 -1
- package/dist/{chunk-P3K2JCJA.js → chunk-D5BXSOSU.js} +3 -3
- package/dist/chunk-E2V5DA3W.js +36 -0
- package/dist/{chunk-WZOGDKCQ.js → chunk-F7CPSRLN.js} +0 -133
- package/dist/chunk-FJBQTZS4.js +17 -0
- package/dist/{chunk-SOSBOS5T.cjs → chunk-G23BTQA5.cjs} +22 -22
- package/dist/{chunk-EUIDTZNQ.cjs → chunk-I3Y2Q3PM.cjs} +59 -308
- package/dist/{chunk-YHUMGBZD.js → chunk-ICTPLVSR.js} +22 -4
- package/dist/{chunk-LRNUZKWV.cjs → chunk-IPUTIUGQ.cjs} +1 -1
- package/dist/{chunk-6GRUVGKU.js → chunk-ITURMC2M.js} +3 -3
- package/dist/{chunk-HYWRU5VX.js → chunk-IXQZHCOF.js} +1 -1
- package/dist/chunk-J5UQHWVL.js +142 -0
- package/dist/{chunk-YBAPT7NL.js → chunk-JC2SHA4A.js} +1 -23
- package/dist/chunk-LRTR4ASZ.cjs +17 -0
- package/dist/{chunk-HUAISCUX.cjs → chunk-M2HG5DJ2.cjs} +18 -18
- package/dist/{chunk-N76AMOKE.cjs → chunk-MDLEGVEN.cjs} +42 -42
- package/dist/chunk-MEGSQUQO.cjs +36 -0
- package/dist/chunk-MLLTWAXH.cjs +276 -0
- package/dist/{chunk-RHPSE2YR.js → chunk-MQ6MGIQM.js} +2 -2
- package/dist/{chunk-PGPFWC35.cjs → chunk-MQGQTKVW.cjs} +51 -33
- package/dist/{chunk-5YWWQ36H.cjs → chunk-O3ZVZSNJ.cjs} +9 -9
- package/dist/{chunk-GCTUOTCW.cjs → chunk-P3PZ63M3.cjs} +35 -35
- package/dist/{chunk-WRZ6C4TU.cjs → chunk-P6WYDBTH.cjs} +4 -4
- package/dist/{chunk-CJ6TBL2N.cjs → chunk-RHEMMGCN.cjs} +16 -16
- package/dist/{chunk-HIMGBZAM.cjs → chunk-RSIKDWOP.cjs} +201 -38
- package/dist/{chunk-SABJMH6M.cjs → chunk-RVGP2XLF.cjs} +2 -135
- package/dist/{chunk-JVRLGV3C.js → chunk-SMTUQWGY.js} +184 -21
- package/dist/{chunk-DMTEQ6SH.js → chunk-SSFMWJDK.js} +4 -4
- package/dist/{chunk-TFF2GTGN.cjs → chunk-SXQHWXEL.cjs} +2 -24
- package/dist/{chunk-IWEVV63O.cjs → chunk-UEYLANO3.cjs} +18 -16
- package/dist/chunk-VR6OGHU5.js +276 -0
- package/dist/{chunk-AF23QK5F.js → chunk-YQ4PQTBB.js} +1 -1
- package/dist/{chunk-B7V34GIH.cjs → chunk-YSGW7VV4.cjs} +88 -88
- package/dist/{chunk-3NS5C7FB.cjs → chunk-YYBW6DF2.cjs} +76 -76
- package/dist/{chunk-UFEDHACQ.js → chunk-Z7BX4TWO.js} +2 -2
- package/dist/{chunk-RUONPPMC.cjs → chunk-ZSE25IZA.cjs} +8 -8
- package/dist/color/index.cjs +7 -3
- package/dist/color/index.js +18 -14
- package/dist/export/index.cjs +8 -6
- package/dist/export/index.js +7 -5
- package/dist/extensions/index.cjs +11 -9
- package/dist/extensions/index.js +10 -8
- package/dist/gradient/index.cjs +33 -31
- package/dist/gradient/index.js +5 -3
- package/dist/image-editor/brush-presets.d.cts +4 -1
- package/dist/image-editor/brush-presets.d.ts +4 -1
- package/dist/image-editor/controller.d.cts +10 -5
- package/dist/image-editor/controller.d.ts +10 -5
- package/dist/image-editor/index.cjs +1090 -1073
- package/dist/image-editor/index.js +37 -20
- package/dist/index.cjs +17 -15
- package/dist/index.js +11 -9
- package/dist/paint-editor/brushes.d.cts +18 -1
- package/dist/paint-editor/brushes.d.ts +18 -1
- package/dist/paint-editor/collaboration.d.cts +38 -0
- package/dist/paint-editor/collaboration.d.ts +38 -0
- package/dist/paint-editor/controller.d.cts +60 -0
- package/dist/paint-editor/controller.d.ts +60 -0
- package/dist/paint-editor/engine.d.cts +7 -0
- package/dist/paint-editor/engine.d.ts +7 -0
- package/dist/paint-editor/index.cjs +1564 -1324
- package/dist/paint-editor/index.js +1198 -958
- package/dist/paint-editor/mark-settings.d.cts +1 -1
- package/dist/paint-editor/mark-settings.d.ts +1 -1
- package/dist/paint-editor/procedural.d.cts +4 -2
- package/dist/paint-editor/procedural.d.ts +4 -2
- package/dist/paint-editor/stamp-tip.d.cts +45 -0
- package/dist/paint-editor/stamp-tip.d.ts +45 -0
- package/dist/paint-editor/stroke.d.cts +4 -0
- package/dist/paint-editor/stroke.d.ts +4 -0
- package/dist/stickers/index.cjs +4 -2
- package/dist/stickers/index.js +6 -4
- package/dist/typography/index.cjs +3 -2
- package/dist/typography/index.js +2 -1
- package/dist/vector/index.cjs +971 -969
- package/dist/vector/index.js +8 -6
- package/dist/video-editor/index.cjs +4 -2
- package/dist/video-editor/index.js +4 -2
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +21 -11
- package/skills/pixerate-brushes-design/SKILL.md +6 -2
- package/skills/pixerate-brushes-design/evals/canvas-chalk.json +8 -8
- package/skills/pixerate-canvas/SKILL.md +3 -2
- package/skills/pixerate-image-editor/SKILL.md +1 -1
- package/skills/pixerate-paint-editor/SKILL.md +5 -1
- package/skills/pixerate-vector/SKILL.md +1 -1
|
@@ -75,7 +75,13 @@ var DEFAULT_PARTICLE = {
|
|
|
75
75
|
dotRotation: "random"
|
|
76
76
|
};
|
|
77
77
|
function normalizeParticle(raw = {}, base = DEFAULT_PARTICLE) {
|
|
78
|
-
const
|
|
78
|
+
const texture = (t) => {
|
|
79
|
+
if (typeof t !== "string") return null;
|
|
80
|
+
const bare = t.startsWith("editor:") ? t.slice(7) : t;
|
|
81
|
+
if (_chunkJSDND7DFcjs.STAMP_KINDS.includes(bare)) return bare;
|
|
82
|
+
return /^[^:\s]+:\S+$/.test(t) && t.length <= 200 ? t : null;
|
|
83
|
+
};
|
|
84
|
+
const textures = Array.isArray(raw.dotTextures) ? raw.dotTextures.map(texture).filter((t) => t !== null).slice(0, MAX_DOT_TEXTURES) : [..._nullishCoalesce(base.dotTextures, () => ( []))];
|
|
79
85
|
return {
|
|
80
86
|
kind: oneOf(raw.kind, PARTICLE_KINDS, base.kind),
|
|
81
87
|
render: oneOf(raw.render, PARTICLE_RENDERS, base.render),
|
|
@@ -204,6 +210,20 @@ function normalizeBehavior(raw = {}, base = DEFAULT_BEHAVIOR) {
|
|
|
204
210
|
multicolor: normalizeMultiColor(_nullishCoalesce(raw.multicolor, () => ( {})), base.multicolor)
|
|
205
211
|
};
|
|
206
212
|
}
|
|
213
|
+
var DEFAULT_SPRAY = { density: 0.5, size: 0.12 };
|
|
214
|
+
function readStamp(raw, base) {
|
|
215
|
+
if (raw === null) return null;
|
|
216
|
+
if (typeof raw !== "string") return base;
|
|
217
|
+
if (_chunkJSDND7DFcjs.STAMP_KINDS.includes(raw)) return `editor:${raw}`;
|
|
218
|
+
return /^[^:\s]+:\S+$/.test(raw) && raw.length <= 200 ? raw : base;
|
|
219
|
+
}
|
|
220
|
+
function readSpray(raw, base) {
|
|
221
|
+
if (raw === null) return null;
|
|
222
|
+
if (!raw || typeof raw !== "object") return base;
|
|
223
|
+
const r = raw;
|
|
224
|
+
const b = _nullishCoalesce(base, () => ( DEFAULT_SPRAY));
|
|
225
|
+
return { density: unit2(r.density, b.density), size: range(r.size, 0.02, 1, b.size) };
|
|
226
|
+
}
|
|
207
227
|
function isWetCapable(brush) {
|
|
208
228
|
return brush.engine === "dab" || brush.engine === "mixer" || brush.engine === "wet" || brush.engine === "impasto";
|
|
209
229
|
}
|
|
@@ -305,6 +325,8 @@ function normalizePaintBrush(raw = {}, base) {
|
|
|
305
325
|
bristle: normalizeBristle(_nullishCoalesce(raw.bristle, () => ( {})), _nullishCoalesce(b.bristle, () => ( DEFAULT_BRISTLE))),
|
|
306
326
|
sticker: normalizeStickerSettings(_nullishCoalesce(raw.sticker, () => ( {})), _nullishCoalesce(b.sticker, () => ( DEFAULT_STICKER))),
|
|
307
327
|
light: normalizeLight(_nullishCoalesce(raw.light, () => ( {})), _nullishCoalesce(b.light, () => ( DEFAULT_LIGHT))),
|
|
328
|
+
stamp: readStamp(raw.stamp, _nullishCoalesce(b.stamp, () => ( null))),
|
|
329
|
+
spray: readSpray(raw.spray, _nullishCoalesce(b.spray, () => ( null))),
|
|
308
330
|
paint,
|
|
309
331
|
...raw.builtin ? { builtin: true } : {}
|
|
310
332
|
};
|
|
@@ -330,6 +352,8 @@ var BASE_BRUSH = {
|
|
|
330
352
|
bristle: { ...DEFAULT_BRISTLE },
|
|
331
353
|
sticker: { ...DEFAULT_STICKER, stamps: [...DEFAULT_STICKER.stamps] },
|
|
332
354
|
light: { ...DEFAULT_LIGHT },
|
|
355
|
+
stamp: null,
|
|
356
|
+
spray: null,
|
|
333
357
|
paint: null
|
|
334
358
|
};
|
|
335
359
|
var builtin = (init) => ({ ...normalizePaintBrush(init), builtin: true });
|
|
@@ -959,6 +983,53 @@ var BUILTIN_BRUSHES = [
|
|
|
959
983
|
engine: "wet",
|
|
960
984
|
tip: { size: 40, hardness: 0.5, spacing: 0.12, opacity: 1, flow: 1, smoothing: 0.2, pressureSize: false, pressureOpacity: true },
|
|
961
985
|
wet: { tool: "blot", strength: 0.7 }
|
|
986
|
+
}),
|
|
987
|
+
// Pens, crayon, chalk and the spray can (their facets: `@pixerate/editor/brushes` presets).
|
|
988
|
+
builtin({
|
|
989
|
+
id: "ballpoint",
|
|
990
|
+
name: "Ballpoint",
|
|
991
|
+
category: "ink",
|
|
992
|
+
tip: { size: 3, hardness: 0.95, spacing: 0.05, opacity: 0.9, smoothing: 0.35, pressureOpacity: true },
|
|
993
|
+
grain: 0.15,
|
|
994
|
+
pressureSmoothing: 0.3,
|
|
995
|
+
dynamics: { minSize: 0.7, opacityJitter: 0.08 }
|
|
996
|
+
}),
|
|
997
|
+
builtin({
|
|
998
|
+
id: "gel-pen",
|
|
999
|
+
name: "Gel pen",
|
|
1000
|
+
category: "ink",
|
|
1001
|
+
tip: { size: 4, spacing: 0.04, smoothing: 0.3 },
|
|
1002
|
+
pressureSmoothing: 0.3,
|
|
1003
|
+
dynamics: { minSize: 0.8 }
|
|
1004
|
+
}),
|
|
1005
|
+
builtin({
|
|
1006
|
+
id: "fineliner",
|
|
1007
|
+
name: "Fineliner",
|
|
1008
|
+
category: "ink",
|
|
1009
|
+
tip: { size: 2, spacing: 0.05, smoothing: 0.4, pressureSize: false }
|
|
1010
|
+
}),
|
|
1011
|
+
builtin({
|
|
1012
|
+
id: "crayon",
|
|
1013
|
+
name: "Crayon",
|
|
1014
|
+
category: "pastel",
|
|
1015
|
+
tip: { size: 14, hardness: 0.7, spacing: 0.06, opacity: 0.9, flow: 0.85, smoothing: 0.2 },
|
|
1016
|
+
grain: 0.9,
|
|
1017
|
+
dynamics: { minSize: 0.6, tiltSize: 0.6, sizeJitter: 0.1, opacityJitter: 0.1 }
|
|
1018
|
+
}),
|
|
1019
|
+
builtin({
|
|
1020
|
+
id: "chalk",
|
|
1021
|
+
name: "Chalk",
|
|
1022
|
+
category: "pastel",
|
|
1023
|
+
tip: { size: 18, hardness: 0.6, spacing: 0.05, opacity: 0.95, flow: 0.8, smoothing: 0.2 },
|
|
1024
|
+
grain: 1,
|
|
1025
|
+
dynamics: { minSize: 0.5, tiltSize: 0.8, sizeJitter: 0.12, scatter: 0.05 }
|
|
1026
|
+
}),
|
|
1027
|
+
builtin({
|
|
1028
|
+
id: "spray-can",
|
|
1029
|
+
name: "Spray can",
|
|
1030
|
+
category: "airbrush",
|
|
1031
|
+
tip: { size: 60, hardness: 0.9, spacing: 0.08, opacity: 0.9, smoothing: 0.2, pressureSize: false, pressureOpacity: true },
|
|
1032
|
+
spray: { density: 0.7, size: 0.04 }
|
|
962
1033
|
})
|
|
963
1034
|
];
|
|
964
1035
|
var DEFAULT_BRUSH_ID = "pencil-6b";
|
|
@@ -998,12 +1069,16 @@ var EDITOR_STAMPS = {
|
|
|
998
1069
|
toEngine: (v) => v.flatMap((ref) => {
|
|
999
1070
|
try {
|
|
1000
1071
|
const stamp = _chunkJSDND7DFcjs.editorStampOf.call(void 0, ref);
|
|
1001
|
-
return stamp ? [stamp] : [];
|
|
1072
|
+
return stamp ? [stamp] : ref.includes(":") ? [ref] : [];
|
|
1002
1073
|
} catch (e3) {
|
|
1003
1074
|
return [];
|
|
1004
1075
|
}
|
|
1005
1076
|
}),
|
|
1006
|
-
toFacet: (v) => v.map((stamp) => `editor:${stamp}`)
|
|
1077
|
+
toFacet: (v) => v.map((stamp) => stamp.includes(":") ? stamp : `editor:${stamp}`)
|
|
1078
|
+
};
|
|
1079
|
+
var ONE_STAMP = {
|
|
1080
|
+
toEngine: (v) => _nullishCoalesce(v[0], () => ( null)),
|
|
1081
|
+
toFacet: (v) => v ? [v] : void 0
|
|
1007
1082
|
};
|
|
1008
1083
|
var f = (facet, engine, engines = ALL, extra = {}) => ({ facet, engine, engines, ...extra });
|
|
1009
1084
|
var each = (facetPrefix, enginePrefix, keys, engines) => keys.map((k) => f(`${facetPrefix}.${k}`, `${enginePrefix}.${k}`, engines));
|
|
@@ -1047,6 +1122,9 @@ var BRUSH_FIELDS = [
|
|
|
1047
1122
|
f("tip.stamps", "particle.dotTextures", ["particle"], { shapes: ["stamp"], map: EDITOR_STAMPS }),
|
|
1048
1123
|
f("motion.waveSpeed", "particle.waveSpeed", ["particle"]),
|
|
1049
1124
|
f("tip.stamps", "sticker.stamps", ["sticker"], { shapes: ["stamp"] }),
|
|
1125
|
+
f("tip.stamps", "stamp", ["dab"], { shapes: ["stamp"], map: ONE_STAMP }),
|
|
1126
|
+
f("marks.density", "spray.density", ["dab"], { marks: ["scatter"] }),
|
|
1127
|
+
f("marks.size", "spray.size", ["dab"], { marks: ["scatter"] }),
|
|
1050
1128
|
...each("marks", "sticker", ["density", "sizeJitter", "rotationJitter", "scatter"], ["sticker"]),
|
|
1051
1129
|
f("marks.colourJitter", "sticker.colorJitter", ["sticker"]),
|
|
1052
1130
|
...each("tip.bristle", "bristle", ["count", "stiffness", "splay", "thickness", "load", "jitter"], ["bristle"])
|
|
@@ -1086,6 +1164,8 @@ var VARIETY_CATEGORY = {
|
|
|
1086
1164
|
pastel: "pastel",
|
|
1087
1165
|
"soft-pastel": "pastel",
|
|
1088
1166
|
"oil-pastel": "pastel",
|
|
1167
|
+
crayon: "pastel",
|
|
1168
|
+
chalk: "pastel",
|
|
1089
1169
|
charcoal: "charcoal",
|
|
1090
1170
|
airbrush: "airbrush",
|
|
1091
1171
|
marker: "marker"
|
|
@@ -1118,17 +1198,18 @@ function resolveBrush(brush, options = {}) {
|
|
|
1118
1198
|
const engine = resolveEngine(brush);
|
|
1119
1199
|
const input = { id: brush.id, name: brush.name, category: resolveCategory(brush, engine), engine };
|
|
1120
1200
|
for (const field of BRUSH_FIELDS) {
|
|
1121
|
-
if (!field.engines.includes(engine) || field.shapes && !field.shapes.includes(brush.tip.shape)) continue;
|
|
1201
|
+
if (!field.engines.includes(engine) || field.shapes && !field.shapes.includes(brush.tip.shape) || field.marks && !field.marks.includes(_nullishCoalesce(_optionalChain([brush, 'access', _16 => _16.marks, 'optionalAccess', _17 => _17.kind]), () => ( "continuous")))) continue;
|
|
1122
1202
|
const v = getPath(brush, field.facet);
|
|
1123
1203
|
if (v !== void 0) setPath(input, field.engine, field.map ? field.map.toEngine(v) : copy(v));
|
|
1124
1204
|
}
|
|
1205
|
+
if (engine === "dab" && _optionalChain([brush, 'access', _18 => _18.marks, 'optionalAccess', _19 => _19.kind]) === "scatter") input.spray = { ..._nullishCoalesce(input.spray, () => ( {})) };
|
|
1125
1206
|
if (engine === "wet") {
|
|
1126
1207
|
setPath(input, "wet.tool", brush.kind === "tool" ? WET_TOOL_OF[brush.tool] : "paint");
|
|
1127
1208
|
const medium = resolveWetMedium(brush);
|
|
1128
1209
|
if (medium) setPath(input, "wet.medium", medium);
|
|
1129
1210
|
}
|
|
1130
1211
|
if (engine === "blender" || engine === "smudge") input.loadsColor = false;
|
|
1131
|
-
const paint = _optionalChain([brush, 'access',
|
|
1212
|
+
const paint = _optionalChain([brush, 'access', _20 => _20.colour, 'optionalAccess', _21 => _21.default]);
|
|
1132
1213
|
if (paint && typeof paint === "object" && "type" in paint && paint.type === "gradient") input.paint = copy(paint);
|
|
1133
1214
|
return normalizePaintBrush({ ...input, ...options.builtin ? { builtin: true } : {} });
|
|
1134
1215
|
}
|
|
@@ -1147,7 +1228,7 @@ var CATEGORY_MEDIUM = {
|
|
|
1147
1228
|
};
|
|
1148
1229
|
function tipShape(b) {
|
|
1149
1230
|
if (b.engine === "bristle") return "bristle";
|
|
1150
|
-
if (b.engine === "sticker" || b.engine === "particle" && b.particle.dotTextures.length > 0) return "stamp";
|
|
1231
|
+
if (b.engine === "sticker" || b.engine === "particle" && b.particle.dotTextures.length > 0 || b.engine === "dab" && b.stamp) return "stamp";
|
|
1151
1232
|
if (b.tip.roundness >= 1) return "round";
|
|
1152
1233
|
return Math.abs(Math.abs(b.tip.angle % 180) - 45) < 1e-9 || Math.abs(Math.abs(b.tip.angle % 180) - 135) < 1e-9 ? "chisel" : "flat";
|
|
1153
1234
|
}
|
|
@@ -1173,7 +1254,7 @@ function skeleton(b) {
|
|
|
1173
1254
|
return { ...brush, marks: { kind: "objects" } };
|
|
1174
1255
|
default: {
|
|
1175
1256
|
const [medium, variety] = _nullishCoalesce(CATEGORY_MEDIUM[b.category], () => ( []));
|
|
1176
|
-
return { ...brush, ...medium ? { medium } : {}, ...variety ? { variety } : {} };
|
|
1257
|
+
return { ...brush, ...medium ? { medium } : {}, ...variety ? { variety } : {}, ...b.engine === "dab" && b.spray ? { marks: { kind: "scatter" } } : {} };
|
|
1177
1258
|
}
|
|
1178
1259
|
}
|
|
1179
1260
|
}
|
|
@@ -1183,7 +1264,7 @@ function migrateBrushV1(raw) {
|
|
|
1183
1264
|
const brush = skeleton(b);
|
|
1184
1265
|
const defaults = resolveBrush(brush);
|
|
1185
1266
|
for (const field of BRUSH_FIELDS) {
|
|
1186
|
-
if (!field.engines.includes(b.engine) || field.shapes && !field.shapes.includes(brush.tip.shape)) continue;
|
|
1267
|
+
if (!field.engines.includes(b.engine) || field.shapes && !field.shapes.includes(brush.tip.shape) || field.marks && !field.marks.includes(_nullishCoalesce(_optionalChain([brush, 'access', _22 => _22.marks, 'optionalAccess', _23 => _23.kind]), () => ( "continuous")))) continue;
|
|
1187
1268
|
const v = getPath(b, field.engine);
|
|
1188
1269
|
if (!equal(v, getPath(defaults, field.engine))) setPath(brush, field.facet, field.map ? field.map.toFacet(v) : copy2(v));
|
|
1189
1270
|
}
|
|
@@ -1196,7 +1277,7 @@ var BRUSH_KINDS = ["mark", "tool"];
|
|
|
1196
1277
|
var BRUSH_MEDIA = ["paint", "ink", "dry", "spray"];
|
|
1197
1278
|
var BRUSH_TOOLS = ["eraser", "blender", "smudge", "water", "dryer", "blow", "blot", "wet-blend", "wet-drag"];
|
|
1198
1279
|
var BRUSH_TIP_SHAPES = ["round", "flat", "chisel", "bristle", "stamp"];
|
|
1199
|
-
var BRUSH_MARKS_KINDS = ["continuous", "particles", "objects"];
|
|
1280
|
+
var BRUSH_MARKS_KINDS = ["continuous", "scatter", "particles", "objects"];
|
|
1200
1281
|
var BRUSH_SURFACES = ["dry", "wet", "thick"];
|
|
1201
1282
|
|
|
1202
1283
|
// src/brushes/schema.ts
|
|
@@ -1284,6 +1365,15 @@ var PARTICLES = object(
|
|
|
1284
1365
|
},
|
|
1285
1366
|
["kind"]
|
|
1286
1367
|
);
|
|
1368
|
+
var SCATTER = object(
|
|
1369
|
+
"A spray (a spray can): each dab lays a seeded scatter of droplets across the tip; jitter and size come from dynamics and the tip. Missing fields take their defaults.",
|
|
1370
|
+
{
|
|
1371
|
+
kind: { type: "string", const: "scatter", description: 'Always "scatter".' },
|
|
1372
|
+
density: unit3("Droplets per dab: 1 + density \xD7 31 (default 0.5)."),
|
|
1373
|
+
size: num(0.02, 1, "Droplet size as a fraction of the tip size (default 0.12).")
|
|
1374
|
+
},
|
|
1375
|
+
["kind"]
|
|
1376
|
+
);
|
|
1287
1377
|
var OBJECTS = object(
|
|
1288
1378
|
"Each mark stays an editable object (a sticker) on a sticker layer; needs a stamp tip. Missing fields take their defaults.",
|
|
1289
1379
|
{
|
|
@@ -1423,7 +1513,7 @@ var BRUSH_JSON_SCHEMA = object(
|
|
|
1423
1513
|
"Tools: eraser removes paint; blender mixes the colours under the tip; smudge drags paint along; water lays clear water (lifts dried paint with behaviour.wet.rewet); dryer dries wet paint; blow pushes water along; blot takes wet paint up; wet-blend evens out wet pigment; wet-drag drags wet paint."
|
|
1424
1514
|
),
|
|
1425
1515
|
tip: TIP,
|
|
1426
|
-
marks: { description: "How the tip is laid along the path (default continuous).", oneOf: [CONTINUOUS, PARTICLES, OBJECTS] },
|
|
1516
|
+
marks: { description: "How the tip is laid along the path (default continuous): continuous dabs, a scatter of spray droplets, particles, or objects (editable stickers).", oneOf: [CONTINUOUS, SCATTER, PARTICLES, OBJECTS] },
|
|
1427
1517
|
dynamics: DYNAMICS,
|
|
1428
1518
|
behaviour: BEHAVIOUR,
|
|
1429
1519
|
light: LIGHT,
|
|
@@ -1434,7 +1524,7 @@ var BRUSH_JSON_SCHEMA = object(
|
|
|
1434
1524
|
);
|
|
1435
1525
|
var BRUSH_FACET_SCHEMAS = {
|
|
1436
1526
|
tip: TIP,
|
|
1437
|
-
marks: { continuous: CONTINUOUS, particles: PARTICLES, objects: OBJECTS },
|
|
1527
|
+
marks: { continuous: CONTINUOUS, scatter: SCATTER, particles: PARTICLES, objects: OBJECTS },
|
|
1438
1528
|
dynamics: DYNAMICS,
|
|
1439
1529
|
behaviour: BEHAVIOUR,
|
|
1440
1530
|
light: LIGHT,
|
|
@@ -1510,7 +1600,7 @@ function readObject(value, schema, path, problems) {
|
|
|
1510
1600
|
const out = {};
|
|
1511
1601
|
for (const [key, v] of Object.entries(value)) {
|
|
1512
1602
|
if (v === void 0) continue;
|
|
1513
|
-
const child = _optionalChain([schema, 'access',
|
|
1603
|
+
const child = _optionalChain([schema, 'access', _24 => _24.properties, 'optionalAccess', _25 => _25[key]]);
|
|
1514
1604
|
if (!child) {
|
|
1515
1605
|
problems.push(`${path}.${key} is not a brush field; dropped.`);
|
|
1516
1606
|
continue;
|
|
@@ -1562,7 +1652,7 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
1562
1652
|
if (rawMarks !== void 0) {
|
|
1563
1653
|
const k = isObject(rawMarks) ? rawMarks.kind : void 0;
|
|
1564
1654
|
const schema = BRUSH_FACET_SCHEMAS.marks[k];
|
|
1565
|
-
if (!schema) problems.push(`marks.kind ${JSON.stringify(k)} is not valid; use continuous, particles or objects. marks dropped.`);
|
|
1655
|
+
if (!schema) problems.push(`marks.kind ${JSON.stringify(k)} is not valid; use continuous, scatter, particles or objects. marks dropped.`);
|
|
1566
1656
|
else brush.marks = readObject(rawMarks, schema, "brush.marks", problems);
|
|
1567
1657
|
}
|
|
1568
1658
|
if (rawColour !== void 0) {
|
|
@@ -1600,7 +1690,15 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
1600
1690
|
delete brush.marks;
|
|
1601
1691
|
}
|
|
1602
1692
|
}
|
|
1603
|
-
if (_optionalChain([brush, 'access',
|
|
1693
|
+
if (_optionalChain([brush, 'access', _26 => _26.marks, 'optionalAccess', _27 => _27.kind]) === "scatter") {
|
|
1694
|
+
const surface = _optionalChain([brush, 'access', _28 => _28.behaviour, 'optionalAccess', _29 => _29.surface]);
|
|
1695
|
+
const why = brush.tip.shape === "bristle" ? "bristle tips lay their own marks" : surface === "wet" || surface === "thick" ? `${surface} paint is not sprayed` : _optionalChain([brush, 'access', _30 => _30.behaviour, 'optionalAccess', _31 => _31.exchange]) ? "a spray does not pick paint up" : null;
|
|
1696
|
+
if (why) {
|
|
1697
|
+
drop("marks", why);
|
|
1698
|
+
delete brush.marks;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
if (_optionalChain([brush, 'access', _32 => _32.marks, 'optionalAccess', _33 => _33.kind]) === "objects" && brush.tip.shape !== "stamp") {
|
|
1604
1702
|
problems.push("marks objects lay stamps: tip.shape set to stamp.");
|
|
1605
1703
|
brush.tip.shape = "stamp";
|
|
1606
1704
|
}
|
|
@@ -1613,15 +1711,7 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
1613
1711
|
delete brush.tip.stamps;
|
|
1614
1712
|
}
|
|
1615
1713
|
if (brush.tip.stamps) {
|
|
1616
|
-
const
|
|
1617
|
-
const stamps = brush.tip.stamps.flatMap((s) => {
|
|
1618
|
-
const ref = _chunkJSDND7DFcjs.normalizeStickerRef.call(void 0, s);
|
|
1619
|
-
if (particles && !_chunkJSDND7DFcjs.editorStampOf.call(void 0, ref)) {
|
|
1620
|
-
problems.push(`brush.tip.stamps "${ref}" dropped: particle marks lay only the editor's stamps (editor:star, editor:dot\u2026).`);
|
|
1621
|
-
return [];
|
|
1622
|
-
}
|
|
1623
|
-
return [ref];
|
|
1624
|
-
});
|
|
1714
|
+
const stamps = brush.tip.stamps.map((s) => _chunkJSDND7DFcjs.normalizeStickerRef.call(void 0, s));
|
|
1625
1715
|
if (stamps.length) brush.tip.stamps = stamps;
|
|
1626
1716
|
else {
|
|
1627
1717
|
drop("tip.stamps", "none of the stamps can be laid");
|
|
@@ -1658,7 +1748,7 @@ function normalizeBrushSpec(raw, problems = []) {
|
|
|
1658
1748
|
if (b.exchange && kind === "tool" && !wetTool) {
|
|
1659
1749
|
drop("behaviour.exchange", `the ${brush.tool} does not pick paint up`);
|
|
1660
1750
|
delete b.exchange;
|
|
1661
|
-
} else if (b.exchange && (_optionalChain([brush, 'access',
|
|
1751
|
+
} else if (b.exchange && (_optionalChain([brush, 'access', _34 => _34.marks, 'optionalAccess', _35 => _35.kind]) === "particles" || _optionalChain([brush, 'access', _36 => _36.marks, 'optionalAccess', _37 => _37.kind]) === "objects" || brush.tip.shape === "bristle")) {
|
|
1662
1752
|
drop("behaviour.exchange", "particle, object and bristle marks do not pick paint up");
|
|
1663
1753
|
delete b.exchange;
|
|
1664
1754
|
}
|
|
@@ -2123,7 +2213,8 @@ var BRUSH_PRESETS = [
|
|
|
2123
2213
|
variety: "neon",
|
|
2124
2214
|
tip: { shape: "round", size: 10, hardness: 0.9, spacing: 0.04 },
|
|
2125
2215
|
dynamics: { smoothing: 0.45, pressureSize: false },
|
|
2126
|
-
light: { amount: 1 }
|
|
2216
|
+
light: { amount: 1 },
|
|
2217
|
+
colour: { palette: ["#f0abfc", "#22d3ee", "#a3e635", "#fb7185", "#fde047"] }
|
|
2127
2218
|
},
|
|
2128
2219
|
{
|
|
2129
2220
|
id: "light-airbrush",
|
|
@@ -2340,6 +2431,77 @@ var BRUSH_PRESETS = [
|
|
|
2340
2431
|
tip: { shape: "round", size: 40, hardness: 0.5, spacing: 0.12 },
|
|
2341
2432
|
dynamics: { smoothing: 0.2, pressureSize: false, pressureOpacity: true },
|
|
2342
2433
|
behaviour: { strength: 0.7 }
|
|
2434
|
+
},
|
|
2435
|
+
// --- Pens, crayon, chalk and the spray can -------------------------------------------
|
|
2436
|
+
// A ballpoint: a fine, hard, even line that lightens with a light touch.
|
|
2437
|
+
{
|
|
2438
|
+
id: "ballpoint",
|
|
2439
|
+
name: "Ballpoint",
|
|
2440
|
+
kind: "mark",
|
|
2441
|
+
medium: "ink",
|
|
2442
|
+
variety: "ballpoint",
|
|
2443
|
+
tip: { shape: "round", size: 3, hardness: 0.95, spacing: 0.05, opacity: 0.9 },
|
|
2444
|
+
dynamics: { smoothing: 0.35, pressureSmoothing: 0.3, pressureOpacity: true, minSize: 0.7, opacityJitter: 0.08 },
|
|
2445
|
+
behaviour: { grain: 0.15 },
|
|
2446
|
+
colour: { default: "#1e3a8a", palette: ["#1e3a8a", "#111827", "#b91c1c", "#166534"] }
|
|
2447
|
+
},
|
|
2448
|
+
// A gel pen: an even, opaque, saturated line.
|
|
2449
|
+
{
|
|
2450
|
+
id: "gel-pen",
|
|
2451
|
+
name: "Gel pen",
|
|
2452
|
+
kind: "mark",
|
|
2453
|
+
medium: "ink",
|
|
2454
|
+
variety: "gel",
|
|
2455
|
+
tip: { shape: "round", size: 4, spacing: 0.04 },
|
|
2456
|
+
dynamics: { smoothing: 0.3, pressureSmoothing: 0.3, minSize: 0.8 },
|
|
2457
|
+
colour: { default: "#111827", palette: ["#111827", "#7c3aed", "#db2777", "#0891b2", "#16a34a", "#f59e0b"] }
|
|
2458
|
+
},
|
|
2459
|
+
// A fineliner: one width, whatever the pressure.
|
|
2460
|
+
{
|
|
2461
|
+
id: "fineliner",
|
|
2462
|
+
name: "Fineliner",
|
|
2463
|
+
kind: "mark",
|
|
2464
|
+
medium: "ink",
|
|
2465
|
+
variety: "fineliner",
|
|
2466
|
+
tip: { shape: "round", size: 2, spacing: 0.05 },
|
|
2467
|
+
dynamics: { smoothing: 0.4, pressureSize: false },
|
|
2468
|
+
colour: { default: "#111827" }
|
|
2469
|
+
},
|
|
2470
|
+
// A wax crayon: waxy, catching the paper's peaks, a little uneven.
|
|
2471
|
+
{
|
|
2472
|
+
id: "crayon",
|
|
2473
|
+
name: "Crayon",
|
|
2474
|
+
kind: "mark",
|
|
2475
|
+
medium: "dry",
|
|
2476
|
+
variety: "crayon",
|
|
2477
|
+
tip: { shape: "round", size: 14, hardness: 0.7, spacing: 0.06, opacity: 0.9, flow: 0.85 },
|
|
2478
|
+
dynamics: { smoothing: 0.2, minSize: 0.6, tiltSize: 0.6, sizeJitter: 0.1, opacityJitter: 0.1 },
|
|
2479
|
+
behaviour: { grain: 0.9 },
|
|
2480
|
+
colour: { default: "#dc2626", palette: ["#dc2626", "#f59e0b", "#facc15", "#16a34a", "#2563eb", "#7c3aed"] }
|
|
2481
|
+
},
|
|
2482
|
+
// Chalk: broad, powdery and grainy. Its default colour is light on dark paper and dark on light.
|
|
2483
|
+
{
|
|
2484
|
+
id: "chalk",
|
|
2485
|
+
name: "Chalk",
|
|
2486
|
+
kind: "mark",
|
|
2487
|
+
medium: "dry",
|
|
2488
|
+
variety: "chalk",
|
|
2489
|
+
tip: { shape: "round", size: 18, hardness: 0.6, spacing: 0.05, opacity: 0.95, flow: 0.8 },
|
|
2490
|
+
dynamics: { smoothing: 0.2, minSize: 0.5, tiltSize: 0.8, sizeJitter: 0.12, scatter: 0.05 },
|
|
2491
|
+
behaviour: { grain: 1 },
|
|
2492
|
+
colour: { default: { light: "#475569", dark: "#f8fafc" }, palette: [{ light: "#475569", dark: "#f8fafc" }, "#fca5a5", "#fde68a", "#93c5fd"] }
|
|
2493
|
+
},
|
|
2494
|
+
// A spray can: a mist of hard droplets, denser the slower it passes.
|
|
2495
|
+
{
|
|
2496
|
+
id: "spray-can",
|
|
2497
|
+
name: "Spray can",
|
|
2498
|
+
kind: "mark",
|
|
2499
|
+
medium: "spray",
|
|
2500
|
+
variety: "spraycan",
|
|
2501
|
+
tip: { shape: "round", size: 60, hardness: 0.9, spacing: 0.08, opacity: 0.9 },
|
|
2502
|
+
marks: { kind: "scatter", density: 0.7, size: 0.04 },
|
|
2503
|
+
dynamics: { smoothing: 0.2, pressureSize: false, pressureOpacity: true },
|
|
2504
|
+
colour: { palette: ["#ef4444", "#f97316", "#facc15", "#22c55e", "#3b82f6", "#a855f7", "#111827", "#f8fafc"] }
|
|
2343
2505
|
}
|
|
2344
2506
|
];
|
|
2345
2507
|
|
|
@@ -2420,26 +2582,26 @@ function checkBrush(brush, profile) {
|
|
|
2420
2582
|
add("tool", "error", `${host} has no ${brush.tool} tool.`, profile.tools.length ? `Use one of: ${list(profile.tools)}.` : `${host} has no tools; use a mark brush.`);
|
|
2421
2583
|
}
|
|
2422
2584
|
if (!profile.tipShapes.includes(brush.tip.shape)) add("tip.shape", "error", `${host} can't lay a ${brush.tip.shape} tip.`, `Set tip.shape to one of: ${list(profile.tipShapes)}.`);
|
|
2423
|
-
const marks = _nullishCoalesce(_optionalChain([brush, 'access',
|
|
2585
|
+
const marks = _nullishCoalesce(_optionalChain([brush, 'access', _38 => _38.marks, 'optionalAccess', _39 => _39.kind]), () => ( "continuous"));
|
|
2424
2586
|
if (!profile.marks.includes(marks)) add("marks", "error", `${host} can't lay ${marks} marks.`, `Use marks ${list(profile.marks)} (remove marks for continuous dabs).`);
|
|
2425
|
-
const surface = _nullishCoalesce(_optionalChain([brush, 'access',
|
|
2587
|
+
const surface = _nullishCoalesce(_optionalChain([brush, 'access', _40 => _40.behaviour, 'optionalAccess', _41 => _41.surface]), () => ( "dry"));
|
|
2426
2588
|
if (brush.kind === "mark" && !profile.surfaces.includes(surface)) add("behaviour.surface", "error", `${host} has no ${surface} surface.`, `Set behaviour.surface to ${list(profile.surfaces)}.`);
|
|
2427
|
-
const ex = _optionalChain([brush, 'access',
|
|
2428
|
-
feature(profile.reservoir, !!_optionalChain([ex, 'optionalAccess',
|
|
2429
|
-
feature(profile.exchange, !_optionalChain([ex, 'optionalAccess',
|
|
2430
|
-
feature(profile.grain, nonZero(_optionalChain([brush, 'access',
|
|
2431
|
-
feature(profile.light, nonZero(_optionalChain([brush, 'access',
|
|
2589
|
+
const ex = _optionalChain([brush, 'access', _42 => _42.behaviour, 'optionalAccess', _43 => _43.exchange]);
|
|
2590
|
+
feature(profile.reservoir, !!_optionalChain([ex, 'optionalAccess', _44 => _44.reservoir]), "behaviour.exchange.reservoir", "a Mixer Brush reservoir", "Remove behaviour.exchange.reservoir.");
|
|
2591
|
+
feature(profile.exchange, !_optionalChain([ex, 'optionalAccess', _45 => _45.reservoir]) && (nonZero(_optionalChain([ex, 'optionalAccess', _46 => _46.pickup])) || !!_optionalChain([ex, 'optionalAccess', _47 => _47.dirty])), "behaviour.exchange", "picking paint up", "Remove behaviour.exchange.");
|
|
2592
|
+
feature(profile.grain, nonZero(_optionalChain([brush, 'access', _48 => _48.behaviour, 'optionalAccess', _49 => _49.grain])), "behaviour.grain", "paper grain", "Set behaviour.grain to 0.");
|
|
2593
|
+
feature(profile.light, nonZero(_optionalChain([brush, 'access', _50 => _50.light, 'optionalAccess', _51 => _51.amount])), "light", "light paint (glow and spill)", "Remove light (or set light.amount to 0).");
|
|
2432
2594
|
const m = brush.motion;
|
|
2433
2595
|
feature(profile.motion, !!m && (!!m.live || nonZero(m.waveSpeed) || m.fps !== void 0), "motion", "animation", "Remove motion.");
|
|
2434
2596
|
const d = _nullishCoalesce(brush.dynamics, () => ( {}));
|
|
2435
2597
|
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.");
|
|
2436
2598
|
feature(profile.tilt, nonZero(d.tiltSize) || nonZero(d.tiltRoundness) || nonZero(d.tiltOpacity), "dynamics.tilt", "tilt dynamics", "Set dynamics.tiltSize, tiltRoundness and tiltOpacity to 0.");
|
|
2437
2599
|
const colour = brush.colour;
|
|
2438
|
-
if (_optionalChain([colour, 'optionalAccess',
|
|
2600
|
+
if (_optionalChain([colour, 'optionalAccess', _52 => _52.default]) !== void 0) {
|
|
2439
2601
|
const kind = brushColourKind(colour.default);
|
|
2440
2602
|
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.`);
|
|
2441
2603
|
}
|
|
2442
|
-
const foreign = [...new Set((_nullishCoalesce(_optionalChain([colour, 'optionalAccess',
|
|
2604
|
+
const foreign = [...new Set((_nullishCoalesce(_optionalChain([colour, 'optionalAccess', _53 => _53.palette]), () => ( []))).map(brushColourKind).filter((k) => !profile.colours.includes(k)))];
|
|
2443
2605
|
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.`);
|
|
2444
2606
|
return { ok: !issues.some((i) => i.severity === "error"), issues };
|
|
2445
2607
|
}
|
|
@@ -2501,7 +2663,7 @@ function degrade(brush, profile) {
|
|
|
2501
2663
|
}
|
|
2502
2664
|
dropped.push(issue);
|
|
2503
2665
|
}
|
|
2504
|
-
if (_optionalChain([b, 'access',
|
|
2666
|
+
if (_optionalChain([b, 'access', _54 => _54.behaviour, 'optionalAccess', _55 => _55.exchange]) && !Object.keys(b.behaviour.exchange).length) delete b.behaviour.exchange;
|
|
2505
2667
|
const after = checkBrush(b, profile).issues.filter((i) => i.severity === "error");
|
|
2506
2668
|
return { brush: b, dropped, issues: after };
|
|
2507
2669
|
}
|
|
@@ -2531,7 +2693,7 @@ function parseBrushLibrary2(raw, problems = []) {
|
|
|
2531
2693
|
if (file && file.version !== void 0 && file.version !== 1 && file.version !== 2) {
|
|
2532
2694
|
throw new BrushLibraryError("invalid", `Brush library version ${JSON.stringify(file.version)} is not supported; this library reads versions 1 and 2.`);
|
|
2533
2695
|
}
|
|
2534
|
-
const v1File = _optionalChain([file, 'optionalAccess',
|
|
2696
|
+
const v1File = _optionalChain([file, 'optionalAccess', _56 => _56.version]) === 1;
|
|
2535
2697
|
const out = [];
|
|
2536
2698
|
items.forEach((item, i) => {
|
|
2537
2699
|
const at = `brushes[${i}]`;
|
|
@@ -2714,7 +2876,7 @@ function snapshotBrushLibrary(library, onChange) {
|
|
|
2714
2876
|
(list2) => {
|
|
2715
2877
|
entries = list2;
|
|
2716
2878
|
user = list2.filter((e) => !e.builtin).map((e) => e.brush);
|
|
2717
|
-
_optionalChain([onChange, 'optionalCall',
|
|
2879
|
+
_optionalChain([onChange, 'optionalCall', _57 => _57()]);
|
|
2718
2880
|
},
|
|
2719
2881
|
() => void 0
|
|
2720
2882
|
);
|
|
@@ -2817,4 +2979,5 @@ function snapshotBrushLibrary(library, onChange) {
|
|
|
2817
2979
|
|
|
2818
2980
|
|
|
2819
2981
|
|
|
2820
|
-
|
|
2982
|
+
|
|
2983
|
+
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.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.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.BUILTIN_BRUSHES = BUILTIN_BRUSHES; exports.DEFAULT_BRUSH_ID = DEFAULT_BRUSH_ID; exports.brushToJSON = brushToJSON; exports.parseBrushLibrary = parseBrushLibrary; exports.BRUSH_FIELDS = BRUSH_FIELDS; exports.getPath = getPath; exports.setPath = setPath; exports.resolveEngine = resolveEngine; exports.resolveWetMedium = resolveWetMedium; exports.resolveCategory = resolveCategory; exports.resolveBrush = resolveBrush; 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.MAX_BRUSH_PALETTE = MAX_BRUSH_PALETTE; exports.BRUSH_WORD = BRUSH_WORD; exports.BRUSH_JSON_SCHEMA = BRUSH_JSON_SCHEMA; exports.BRUSH_FACET_SCHEMAS = BRUSH_FACET_SCHEMAS; exports.WET_BRUSH_TOOLS = WET_BRUSH_TOOLS; exports.normalizeBrushSpec = normalizeBrushSpec; exports.BRUSH_PRESETS = BRUSH_PRESETS; 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.listPresets = listPresets; exports.degrade = degrade; exports.BrushLibraryError = BrushLibraryError; exports.parseBrushLibrary2 = parseBrushLibrary2; exports.createBrushLibrary = createBrushLibrary; exports.closest = closest; exports.snapshotBrushLibrary = snapshotBrushLibrary;
|
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
7
|
var _chunkJSDND7DFcjs = require('./chunk-JSDND7DF.cjs');
|
|
12
8
|
|
|
13
9
|
|
|
@@ -16,129 +12,6 @@ var _chunkU67EN7GGcjs = require('./chunk-U67EN7GG.cjs');
|
|
|
16
12
|
|
|
17
13
|
var _chunkW5M3J7PVcjs = require('./chunk-W5M3J7PV.cjs');
|
|
18
14
|
|
|
19
|
-
// src/stickers/tools.ts
|
|
20
|
-
var READ = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
21
|
-
var WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
22
|
-
function stickerForAgent(provider, s) {
|
|
23
|
-
const { id, thumbnail: _thumbnail, ...rest } = s;
|
|
24
|
-
return { ref: _chunkJSDND7DFcjs.stickerRefOf.call(void 0, provider, id), ...rest };
|
|
25
|
-
}
|
|
26
|
-
async function knownRefs(provider, cap = 500) {
|
|
27
|
-
const refs = [];
|
|
28
|
-
let after;
|
|
29
|
-
while (refs.length < cap) {
|
|
30
|
-
const page = await provider.list({ limit: _chunkJSDND7DFcjs.MAX_STICKER_PAGE, ...after ? { after } : {} });
|
|
31
|
-
refs.push(...page.items.map((s) => _chunkJSDND7DFcjs.stickerRefOf.call(void 0, provider, s.id)));
|
|
32
|
-
if (!page.next || !page.items.length) break;
|
|
33
|
-
after = page.next;
|
|
34
|
-
}
|
|
35
|
-
return refs;
|
|
36
|
-
}
|
|
37
|
-
async function describeStickerRef(provider, ref) {
|
|
38
|
-
_chunkJSDND7DFcjs.parseStickerRef.call(void 0, ref);
|
|
39
|
-
const id = _chunkJSDND7DFcjs.stickerIdFor.call(void 0, provider, ref);
|
|
40
|
-
const found = id === null ? void 0 : await provider.describe(id);
|
|
41
|
-
if (found) return found;
|
|
42
|
-
const near = _chunkJSDND7DFcjs.closestStickerRefs.call(void 0, ref, await knownRefs(provider));
|
|
43
|
-
const owner = _chunkJSDND7DFcjs.parseStickerRef.call(void 0, ref).provider;
|
|
44
|
-
const where = id === null && !provider.namespaced ? ` The sticker library is "${provider.id}", not "${owner}".` : "";
|
|
45
|
-
throw new (0, _chunkU67EN7GGcjs.StickerError)("unknown_sticker", `No sticker "${ref}".${where} Closest: ${near.join(", ") || "none"}; find_stickers lists them.`);
|
|
46
|
-
}
|
|
47
|
-
function createStickerTools(options) {
|
|
48
|
-
const find = {
|
|
49
|
-
name: "find_stickers",
|
|
50
|
-
title: "Find stickers",
|
|
51
|
-
description: "Searches the sticker library (the editor's own stamps unless the host plugged in its own): words in the name, tags, category or description, filtered by category, tags and commercial licence, a small page at a time. Returns each sticker's ref (provider:id, for the tools that spray or place stickers), name, category, tags, natural width and height, formats, whether it is tintable (recoloured to the paint colour) and its licence, plus total and next (pass as after for the next page) and the categories. Changes nothing.",
|
|
52
|
-
inputSchema: {
|
|
53
|
-
type: "object",
|
|
54
|
-
properties: {
|
|
55
|
-
query: { type: "string", maxLength: 200, description: "Words to match (default: list everything)." },
|
|
56
|
-
category: { type: "string", description: "Only this category (the result lists them)." },
|
|
57
|
-
tags: { type: "array", maxItems: 10, items: { type: "string", description: "A tag." }, description: "Only stickers with every one of these tags." },
|
|
58
|
-
commercial: { type: "boolean", description: "true: only stickers whose licence allows commercial use." },
|
|
59
|
-
limit: { type: "integer", minimum: 1, maximum: _chunkJSDND7DFcjs.MAX_STICKER_PAGE, description: "Page size (default 24)." },
|
|
60
|
-
after: { type: "string", description: "next from the previous page." }
|
|
61
|
-
},
|
|
62
|
-
additionalProperties: false
|
|
63
|
-
},
|
|
64
|
-
annotations: { title: "Find stickers", ...READ },
|
|
65
|
-
handler: async ({ query, category, tags, commercial, limit, after }) => {
|
|
66
|
-
const p = options.provider();
|
|
67
|
-
const categories = await _asyncNullishCoalesce(await _optionalChain([p, 'access', _2 => _2.categories, 'optionalCall', _3 => _3()]), async () => ( null));
|
|
68
|
-
if (category !== void 0 && categories && !categories.some((c) => c.id === category)) {
|
|
69
|
-
throw new (0, _chunkU67EN7GGcjs.StickerError)("invalid_argument", `No category "${category}" in "${p.name}"; categories: ${categories.map((c) => c.id).join(", ")}.`);
|
|
70
|
-
}
|
|
71
|
-
const o = { ...category !== void 0 ? { category } : {}, ...tags ? { tags } : {}, ...commercial ? { licence: { commercial: true } } : {}, ...limit !== void 0 ? { limit } : {}, ...after !== void 0 ? { after } : {} };
|
|
72
|
-
const q = typeof query === "string" ? query.trim() : "";
|
|
73
|
-
if (q && !p.capabilities.supportsSearch) throw new (0, _chunkU67EN7GGcjs.StickerError)("invalid_argument", `"${p.name}" can't search; leave query out and filter by category instead.`);
|
|
74
|
-
const page = q ? await p.search(q, o) : await p.list(o);
|
|
75
|
-
return { provider: p.id, items: page.items.map((s) => stickerForAgent(p, s)), total: page.total, ...page.next ? { next: page.next } : {}, ...categories ? { categories } : {} };
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
const describe = {
|
|
79
|
-
name: "describe_sticker",
|
|
80
|
-
title: "Describe a sticker",
|
|
81
|
-
description: "Everything about one sticker by ref (from find_stickers): name, category, tags, natural size, formats, tintable, licence (with any attribution it asks for), dominant colours, variants and its outline as SVG path data (silhouette). An unknown ref is refused with the closest refs. Changes nothing.",
|
|
82
|
-
inputSchema: { type: "object", properties: { ref: { type: "string", description: "Sticker ref provider:id from find_stickers (e.g. editor:star)." } }, required: ["ref"], additionalProperties: false },
|
|
83
|
-
annotations: { title: "Describe a sticker", ...READ },
|
|
84
|
-
handler: async ({ ref }) => {
|
|
85
|
-
const p = options.provider();
|
|
86
|
-
const d = await describeStickerRef(p, ref);
|
|
87
|
-
const { thumbnail: _thumbnail, id, ...rest } = d;
|
|
88
|
-
return { ref: _chunkJSDND7DFcjs.stickerRefOf.call(void 0, p, id), ...rest };
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
return options.insert ? [find, describe, createInsertStickerTool(options.provider, options.insert)] : [find, describe];
|
|
92
|
-
}
|
|
93
|
-
async function loadForHost(provider, ref, d, host, colour, size) {
|
|
94
|
-
const id = _chunkJSDND7DFcjs.stickerIdFor.call(void 0, provider, ref);
|
|
95
|
-
const format = d.formats.includes(host.format) ? host.format : _nullishCoalesce(d.formats[0], () => ( host.format));
|
|
96
|
-
return provider.load(id, { format, ...format === "png" ? { size: Math.max(8, Math.min(_nullishCoalesce(provider.capabilities.maxSize, () => ( 1024)), Math.round(size))) } : {}, ...colour && d.tintable ? { colour } : {} });
|
|
97
|
-
}
|
|
98
|
-
async function insertSticker(provider, host, options) {
|
|
99
|
-
const d = await describeStickerRef(provider, options.ref);
|
|
100
|
-
if (options.color !== void 0 && !d.tintable) throw new (0, _chunkU67EN7GGcjs.StickerError)("invalid_argument", `"${options.ref}" is not tintable (its art has its own colours); leave color out, or pick a tintable sticker (find_stickers lists tintable).`);
|
|
101
|
-
if (options.width !== void 0 && !(options.width > 0)) throw new (0, _chunkU67EN7GGcjs.StickerError)("invalid_argument", `width must be a positive size, got ${options.width}.`);
|
|
102
|
-
const w = _nullishCoalesce(options.width, () => ( d.width));
|
|
103
|
-
const h = w * d.height / d.width;
|
|
104
|
-
const centre = host.defaultCentre();
|
|
105
|
-
const asset = await loadForHost(provider, options.ref, d, host, options.color, Math.max(w, h));
|
|
106
|
-
const ref = _chunkJSDND7DFcjs.stickerRefOf.call(void 0, provider, d.id);
|
|
107
|
-
const made = await host.insert({ ref, description: d, asset, x: _nullishCoalesce(options.x, () => ( centre.x)), y: _nullishCoalesce(options.y, () => ( centre.y)), width: w, height: h, ...options.color ? { colour: options.color.toLowerCase() } : {} });
|
|
108
|
-
return { ...made, ref, width: w, height: h, licence: d.licence };
|
|
109
|
-
}
|
|
110
|
-
function createInsertStickerTool(provider, host) {
|
|
111
|
-
return {
|
|
112
|
-
name: "insert_sticker",
|
|
113
|
-
title: "Insert a sticker",
|
|
114
|
-
description: `Puts one sticker from the sticker library (ref from find_stickers) into the document as a new ${host.noun}, centred at x, y and width wide (its natural aspect kept; default its natural size), tinted to color when the sticker is tintable. Its art is loaded first; an unknown ref is refused with the closest ones. One undo step. Returns the new ${host.noun}'s id (for the editor's own tools, such as effects on it), the ref and its licence (credit any attribution it asks for).`,
|
|
115
|
-
inputSchema: {
|
|
116
|
-
type: "object",
|
|
117
|
-
properties: {
|
|
118
|
-
ref: { type: "string", minLength: 1, description: "Sticker ref provider:id from find_stickers (e.g. editor:star)." },
|
|
119
|
-
x: { type: "number", description: "Centre x in document units (default the middle of the view or document)." },
|
|
120
|
-
y: { type: "number", description: "Centre y in document units (default the middle of the view or document)." },
|
|
121
|
-
width: { type: "number", exclusiveMinimum: 0, maximum: 1e4, description: "Width in document units (default the natural width); the height follows the aspect." },
|
|
122
|
-
color: { type: "string", pattern: "^#[0-9a-fA-F]{6}$", description: "Tint #rrggbb for tintable stickers (default the sticker's own colour); refused for stickers that are not tintable." }
|
|
123
|
-
},
|
|
124
|
-
required: ["ref"],
|
|
125
|
-
additionalProperties: false
|
|
126
|
-
},
|
|
127
|
-
annotations: { title: "Insert a sticker", ...WRITE },
|
|
128
|
-
handler: ({ ref, x, y, width, color }) => insertSticker(provider(), host, { ref, x, y, width, color })
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
function createStickerToolProvider(options) {
|
|
132
|
-
return {
|
|
133
|
-
id: _nullishCoalesce(options.id, () => ( "stickers")),
|
|
134
|
-
namespace: options.namespace,
|
|
135
|
-
title: "Stickers",
|
|
136
|
-
description: "Find and describe stickers from the sticker library, by ref (provider:id), for the editors that spray or place them.",
|
|
137
|
-
skill: "pixerate-stickers",
|
|
138
|
-
tools: createStickerTools(options)
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
15
|
// src/stickers/editor.ts
|
|
143
16
|
var BOX = 100;
|
|
144
17
|
var GRID = 128;
|
|
@@ -382,7 +255,7 @@ var StickerBrowser = (_class = class {
|
|
|
382
255
|
this.next = void 0;
|
|
383
256
|
this.set({ loading: true, error: null, items: [], total: 0, hasMore: false, provider: p.name });
|
|
384
257
|
try {
|
|
385
|
-
const categories = await _asyncNullishCoalesce(await _optionalChain([p, 'access',
|
|
258
|
+
const categories = await _asyncNullishCoalesce(await _optionalChain([p, 'access', _2 => _2.categories, 'optionalCall', _3 => _3()]), async () => ( []));
|
|
386
259
|
if (run !== this.run) return;
|
|
387
260
|
this.set({ categories });
|
|
388
261
|
await this.page(run, p, true);
|
|
@@ -427,10 +300,4 @@ var StickerBrowser = (_class = class {
|
|
|
427
300
|
|
|
428
301
|
|
|
429
302
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
exports.stickerForAgent = stickerForAgent; exports.describeStickerRef = describeStickerRef; exports.createStickerTools = createStickerTools; exports.insertSticker = insertSticker; exports.createInsertStickerTool = createInsertStickerTool; exports.createStickerToolProvider = createStickerToolProvider; exports.stampOutline = stampOutline; exports.stampPixels = stampPixels; exports.editorStickers = editorStickers; exports.StickerBrowser = StickerBrowser;
|
|
303
|
+
exports.stampOutline = stampOutline; exports.stampPixels = stampPixels; exports.editorStickers = editorStickers; exports.StickerBrowser = StickerBrowser;
|