@pixerate/editor 0.275.1 → 0.277.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 +62 -62
- package/dist/animation-editor/index.js +6 -6
- package/dist/brushes/index.cjs +84 -71
- package/dist/brushes/index.js +20 -7
- package/dist/brushes/patch.d.cts +4 -4
- package/dist/brushes/patch.d.ts +4 -4
- package/dist/brushes/profiles.d.cts +4 -0
- package/dist/brushes/profiles.d.ts +4 -0
- package/dist/brushes/schema.d.cts +2 -0
- package/dist/brushes/schema.d.ts +2 -0
- package/dist/brushes/types.d.cts +32 -1
- package/dist/brushes/types.d.ts +32 -1
- package/dist/{brushstrokeRender-2RQL46WB.cjs → brushstrokeRender-7HOMKZNO.cjs} +21 -21
- package/dist/{brushstrokeRender-WGY4DZHF.js → brushstrokeRender-EIK3625T.js} +5 -5
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-T6KNJVBP.cjs → chunk-4NZTK7LM.cjs} +35 -35
- package/dist/{chunk-LMG57L5A.js → chunk-CTHWXW5M.js} +121 -8
- package/dist/{chunk-43XJC3PP.js → chunk-DWPFGWW5.js} +1 -1
- package/dist/{chunk-MSWLJI4G.js → chunk-FNIWHSLI.js} +2 -2
- package/dist/{chunk-JDXWLCXF.cjs → chunk-H3EME3S5.cjs} +2 -2
- package/dist/{chunk-Y2ISSVPH.js → chunk-HHX7ST6Z.js} +167 -9
- package/dist/{chunk-6QNDGMK7.cjs → chunk-HRUK5TFW.cjs} +187 -45
- package/dist/{chunk-NIBFKXMD.cjs → chunk-IFWLZZCW.cjs} +619 -2
- package/dist/{chunk-W6JDUXP3.js → chunk-J23JOHPR.js} +1 -1
- package/dist/{chunk-HVO6XCI4.js → chunk-JPB65KQ6.js} +1 -1
- package/dist/{chunk-Y354ETAE.cjs → chunk-JVFGK3DK.cjs} +69 -58
- package/dist/{chunk-ACTHSQOI.js → chunk-LDZOXESA.js} +618 -1
- package/dist/{chunk-IEEY5RJV.js → chunk-LZE2QZCT.js} +1 -1
- package/dist/{chunk-DHC4E2DU.cjs → chunk-MITQGHN3.cjs} +121 -8
- package/dist/{chunk-75SYKUOT.js → chunk-N4MCWQZ7.js} +1 -1
- package/dist/{chunk-G5TCMKX5.js → chunk-NJLPW4MM.js} +17 -6
- package/dist/{chunk-STLTOISW.cjs → chunk-NPPMKMCU.cjs} +17 -17
- package/dist/{chunk-OLZXXAER.cjs → chunk-PEQWARCP.cjs} +408 -250
- package/dist/{chunk-ZM7IKQ4X.js → chunk-PPDUCZZV.js} +152 -10
- package/dist/{chunk-RAPNRK4R.cjs → chunk-QBZEC2JJ.cjs} +88 -88
- package/dist/{chunk-RJGW3RQS.js → chunk-ROURHJYT.js} +1 -1
- package/dist/{chunk-62MFUHSI.cjs → chunk-UQXULAMQ.cjs} +16 -16
- package/dist/{chunk-YYZC2EQO.cjs → chunk-VNF7A2JA.cjs} +23 -23
- package/dist/{chunk-C6VB7CPY.cjs → chunk-WFSYZO5Z.cjs} +1 -1
- package/dist/image-editor/index.cjs +880 -852
- package/dist/image-editor/index.js +36 -8
- package/dist/paint/index.cjs +33 -5
- package/dist/paint/index.d.cts +1 -0
- package/dist/paint/index.d.ts +1 -0
- package/dist/paint/index.js +32 -4
- package/dist/paint/live-patterns.d.cts +149 -0
- package/dist/paint/live-patterns.d.ts +149 -0
- package/dist/paint/wet/world.d.cts +13 -0
- package/dist/paint/wet/world.d.ts +13 -0
- package/dist/paint-editor/brush-model.d.cts +21 -1
- package/dist/paint-editor/brush-model.d.ts +21 -1
- package/dist/paint-editor/controller.d.cts +102 -1
- package/dist/paint-editor/controller.d.ts +102 -1
- package/dist/paint-editor/document.d.cts +8 -1
- package/dist/paint-editor/document.d.ts +8 -1
- package/dist/paint-editor/ferro-tools.d.cts +10 -0
- package/dist/paint-editor/ferro-tools.d.ts +10 -0
- package/dist/paint-editor/ferro.d.cts +134 -0
- package/dist/paint-editor/ferro.d.ts +134 -0
- package/dist/paint-editor/index.cjs +2291 -904
- package/dist/paint-editor/index.d.cts +2 -0
- package/dist/paint-editor/index.d.ts +2 -0
- package/dist/paint-editor/index.js +1533 -146
- package/dist/paint-editor/stroke.d.cts +14 -0
- package/dist/paint-editor/stroke.d.ts +14 -0
- package/dist/paint-editor/thick.d.cts +15 -2
- package/dist/paint-editor/thick.d.ts +15 -2
- package/dist/paint-editor/ui.d.cts +7 -1
- package/dist/paint-editor/ui.d.ts +7 -1
- package/dist/paint-editor/wet-tools.d.cts +42 -0
- package/dist/paint-editor/wet-tools.d.ts +42 -0
- package/dist/paint-editor/wet.d.cts +22 -1
- package/dist/paint-editor/wet.d.ts +22 -1
- package/dist/vector/index.cjs +1002 -1002
- package/dist/vector/index.js +7 -7
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +1 -0
- package/skills/pixerate-paint-editor/SKILL.md +11 -29
- package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
- package/skills/pixerate-paint-editor/references/ferrofluid.md +36 -0
|
@@ -27,7 +27,8 @@ var _chunkPFHJS4HEcjs = require('./chunk-PFHJS4HE.cjs');
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
|
|
31
|
+
var _chunkHRUK5TFWcjs = require('./chunk-HRUK5TFW.cjs');
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
var _chunkW5M3J7PVcjs = require('./chunk-W5M3J7PV.cjs');
|
|
@@ -38,13 +39,20 @@ var _chunkXFM3OCHUcjs = require('./chunk-XFM3OCHU.cjs');
|
|
|
38
39
|
// src/brushes/patch.ts
|
|
39
40
|
var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
40
41
|
var copy = (v) => JSON.parse(JSON.stringify(v));
|
|
41
|
-
var FACETS =
|
|
42
|
+
var FACETS = _chunkHRUK5TFWcjs.BRUSH_JSON_SCHEMA.properties;
|
|
42
43
|
var BRUSH_PATCH_PROPERTIES = (() => {
|
|
43
44
|
const { id: _id, name: _name, ...rest } = FACETS;
|
|
44
45
|
const { required: _r, ...tip } = rest.tip;
|
|
45
|
-
|
|
46
|
+
const ferro = {
|
|
47
|
+
description: "Liquid ferrofluid paint: 0..1 (amount), or { amount, wavelength, threshold }. Rises into glossy Rosensweig spikes near magnets until cured.",
|
|
48
|
+
anyOf: [
|
|
49
|
+
{ type: "number", minimum: 0, maximum: 1, description: "How much liquid ferrofluid the brush lays per dab (0..1)." },
|
|
50
|
+
_chunkHRUK5TFWcjs.BRUSH_FACET_SCHEMAS.ferro
|
|
51
|
+
]
|
|
52
|
+
};
|
|
53
|
+
return { ...rest, tip: { ...tip, description: `${tip.description} In a patch, shape may be left out to keep it.` }, ferro };
|
|
46
54
|
})();
|
|
47
|
-
var UNSETTABLE_BRUSH_FACETS = ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "motion", "colour"];
|
|
55
|
+
var UNSETTABLE_BRUSH_FACETS = ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "ferro", "motion", "livePatterns", "colour"];
|
|
48
56
|
var BRUSH_UNSET_PROPERTY = {
|
|
49
57
|
type: "array",
|
|
50
58
|
minItems: 1,
|
|
@@ -54,9 +62,11 @@ var BRUSH_UNSET_PROPERTY = {
|
|
|
54
62
|
};
|
|
55
63
|
function mergeBrushPatch(base, patch, path = "") {
|
|
56
64
|
const out = { ...base };
|
|
57
|
-
for (const [k,
|
|
58
|
-
if (
|
|
59
|
-
const
|
|
65
|
+
for (const [k, rawV] of Object.entries(patch)) {
|
|
66
|
+
if (rawV === void 0) continue;
|
|
67
|
+
const v = path === "" && k === "ferro" && typeof rawV === "number" ? { amount: rawV } : rawV;
|
|
68
|
+
const rawOld = out[k];
|
|
69
|
+
const old = path === "" && k === "ferro" && typeof rawOld === "number" ? { amount: rawOld } : rawOld;
|
|
60
70
|
const replaceMarks = path === "" && k === "marks" && isObject(old) && isObject(v) && old.kind !== v.kind;
|
|
61
71
|
out[k] = isObject(v) && isObject(old) && !replaceMarks ? mergeBrushPatch(old, v, `${path}${k}.`) : copy(v);
|
|
62
72
|
}
|
|
@@ -557,7 +567,7 @@ function idMaker(prefix) {
|
|
|
557
567
|
return (name) => {
|
|
558
568
|
const base = `${prefix}-${slug(name, 20) || "brush"}`.slice(0, 58).replace(/-+$/, "");
|
|
559
569
|
let id = base;
|
|
560
|
-
for (let n = 2; used.has(id) || !
|
|
570
|
+
for (let n = 2; used.has(id) || !_chunkHRUK5TFWcjs.BRUSH_ID.test(id); n++) id = `${base}-${n}`;
|
|
561
571
|
used.add(id);
|
|
562
572
|
return id;
|
|
563
573
|
};
|
|
@@ -582,9 +592,9 @@ function readAbrPack(bytes, name, prefix, licence, pack) {
|
|
|
582
592
|
return;
|
|
583
593
|
}
|
|
584
594
|
try {
|
|
585
|
-
const source =
|
|
595
|
+
const source = _chunkHRUK5TFWcjs.brushSourceFromMask.call(void 0, { id: `${brushId}-shape`, name: label, licence, origin: `${name}.abr` }, tip.width, tip.height, tip.mask);
|
|
586
596
|
pack.sources.push(source);
|
|
587
|
-
pack.brushes.push({ ...base, tip: { shape: "stamp", size: clamp2(Math.max(tip.width, tip.height), 1, 2500), spacing: _nullishCoalesce(tip.spacing, () => ( 0.25)), stamps: [
|
|
597
|
+
pack.brushes.push({ ...base, tip: { shape: "stamp", size: clamp2(Math.max(tip.width, tip.height), 1, 2500), spacing: _nullishCoalesce(tip.spacing, () => ( 0.25)), stamps: [_chunkHRUK5TFWcjs.brushSourceRef.call(void 0, source.id)] } });
|
|
588
598
|
} catch (e) {
|
|
589
599
|
pack.unsupported.push(`"${label}": ${e.message}`);
|
|
590
600
|
}
|
|
@@ -626,7 +636,7 @@ function readProcreatePack(bytes, name, prefix, licence, pack) {
|
|
|
626
636
|
const e = byName.get(`${dir}${file}`);
|
|
627
637
|
if (!e) return null;
|
|
628
638
|
try {
|
|
629
|
-
const s =
|
|
639
|
+
const s = _chunkHRUK5TFWcjs.makeBrushSource.call(void 0, { id: `${brushId}-${kind}`, name: `${label} ${kind}`, image: e.read(), channel: "lightness", licence: [licence, terms].filter(Boolean).join("\n\n") || void 0, origin: `${where}/${file}` });
|
|
630
640
|
pack.sources.push(s);
|
|
631
641
|
return s;
|
|
632
642
|
} catch (err) {
|
|
@@ -647,8 +657,8 @@ function readProcreatePack(bytes, name, prefix, licence, pack) {
|
|
|
647
657
|
shape: shape ? "stamp" : "round",
|
|
648
658
|
size: 40,
|
|
649
659
|
...plot !== void 0 ? { spacing: plot } : {},
|
|
650
|
-
...shape ? { stamps: [
|
|
651
|
-
...grain ? { grain: { source:
|
|
660
|
+
...shape ? { stamps: [_chunkHRUK5TFWcjs.brushSourceRef.call(void 0, shape.id)] } : {},
|
|
661
|
+
...grain ? { grain: { source: _chunkHRUK5TFWcjs.brushSourceRef.call(void 0, grain.id), mode: "moving" } } : {}
|
|
652
662
|
}
|
|
653
663
|
});
|
|
654
664
|
if (!settings) pack.unsupported.push(`"${label}": its Brush.archive could not be read; the brush takes its name from the file and default settings.`);
|
|
@@ -702,17 +712,17 @@ async function importBrushFile(library, file, options = {}) {
|
|
|
702
712
|
// src/brushes/tools.ts
|
|
703
713
|
var READ = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
704
714
|
var WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
705
|
-
var FACETS2 =
|
|
715
|
+
var FACETS2 = _chunkHRUK5TFWcjs.BRUSH_JSON_SCHEMA.properties;
|
|
706
716
|
var ID = { type: "string", pattern: String(FACETS2.id.pattern), description: "Brush id from list_brush_presets (lowercase letters, digits and dashes)." };
|
|
707
717
|
var FACET_PROPS = BRUSH_PATCH_PROPERTIES;
|
|
708
|
-
var HOSTS = Object.keys(
|
|
718
|
+
var HOSTS = Object.keys(_chunkHRUK5TFWcjs.BRUSH_HOST_PROFILES);
|
|
709
719
|
var copy2 = (v) => JSON.parse(JSON.stringify(v));
|
|
710
720
|
var merge = mergeBrushPatch;
|
|
711
721
|
var changedPaths = changedBrushPaths;
|
|
712
722
|
function summary(entry, profile, withCheck) {
|
|
713
723
|
const b = entry.brush;
|
|
714
|
-
const engine =
|
|
715
|
-
const check = withCheck ?
|
|
724
|
+
const engine = _chunkHRUK5TFWcjs.resolveEngine.call(void 0, b);
|
|
725
|
+
const check = withCheck ? _chunkHRUK5TFWcjs.checkBrush.call(void 0, b, profile) : null;
|
|
716
726
|
return {
|
|
717
727
|
id: b.id,
|
|
718
728
|
name: b.name,
|
|
@@ -721,47 +731,48 @@ function summary(entry, profile, withCheck) {
|
|
|
721
731
|
...b.medium ? { medium: b.medium } : {},
|
|
722
732
|
...b.variety ? { variety: b.variety } : {},
|
|
723
733
|
...b.tool ? { tool: b.tool } : {},
|
|
724
|
-
category:
|
|
734
|
+
category: _chunkHRUK5TFWcjs.resolveCategory.call(void 0, b, engine),
|
|
725
735
|
engine,
|
|
726
736
|
tip: b.tip.shape,
|
|
727
737
|
...b.tip.size !== void 0 ? { size: b.tip.size } : {},
|
|
728
738
|
marks: _nullishCoalesce(_optionalChain([b, 'access', _16 => _16.marks, 'optionalAccess', _17 => _17.kind]), () => ( "continuous")),
|
|
729
739
|
surface: _nullishCoalesce(_optionalChain([b, 'access', _18 => _18.behaviour, 'optionalAccess', _19 => _19.surface]), () => ( "dry")),
|
|
730
740
|
..._optionalChain([b, 'access', _20 => _20.light, 'optionalAccess', _21 => _21.amount]) ? { light: b.light.amount } : {},
|
|
731
|
-
..._optionalChain([b, 'access', _22 => _22.
|
|
741
|
+
..._optionalChain([b, 'access', _22 => _22.ferro, 'optionalAccess', _23 => _23.amount]) ? { ferro: b.ferro.amount } : {},
|
|
742
|
+
..._optionalChain([b, 'access', _24 => _24.tags, 'optionalAccess', _25 => _25.length]) ? { tags: b.tags } : {},
|
|
732
743
|
...check ? { renderable: check.ok } : {}
|
|
733
744
|
};
|
|
734
745
|
}
|
|
735
746
|
var refusal = (check, host) => `${host.name} can't use this brush: ${check.issues.filter((i) => i.severity === "error").map((i) => `${i.facet}: ${i.reason} ${i.fix}`).join(" ")} (check_brush lists every issue; nothing was saved.)`;
|
|
736
747
|
var warnings = (check) => check.issues.filter((i) => i.severity === "warning");
|
|
737
748
|
function createBrushLibraryTools(library, options = {}) {
|
|
738
|
-
const profile = _nullishCoalesce(options.profile, () => (
|
|
749
|
+
const profile = _nullishCoalesce(options.profile, () => ( _chunkHRUK5TFWcjs.PAINT_PROFILE));
|
|
739
750
|
const hostOf = (id) => {
|
|
740
751
|
if (id === void 0) return profile;
|
|
741
|
-
const p =
|
|
742
|
-
if (!p) throw new (0,
|
|
752
|
+
const p = _chunkHRUK5TFWcjs.BRUSH_HOST_PROFILES[id];
|
|
753
|
+
if (!p) throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("invalid", `No host "${id}"; use one of: ${HOSTS.join(", ")}.`);
|
|
743
754
|
return p;
|
|
744
755
|
};
|
|
745
756
|
const entry = async (id) => {
|
|
746
757
|
const found = await library.get(id);
|
|
747
758
|
if (found) return found;
|
|
748
759
|
const ids = (await library.list()).map((e) => e.brush.id);
|
|
749
|
-
throw new (0,
|
|
760
|
+
throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("unknown_brush", `No brush "${id}". ${_chunkHRUK5TFWcjs.closest.call(void 0, id, ids)}list_brush_presets lists them.`);
|
|
750
761
|
};
|
|
751
762
|
const checkFor = async (brush, p) => {
|
|
752
|
-
const check2 =
|
|
763
|
+
const check2 = _chunkHRUK5TFWcjs.checkBrush.call(void 0, brush, p);
|
|
753
764
|
const issues = [...check2.issues];
|
|
754
765
|
const refs = [...(_nullishCoalesce(brush.tip.stamps, () => ( []))).map((r) => ["tip.stamps", r]), ...brush.tip.grain ? [["tip.grain.source", brush.tip.grain.source]] : []];
|
|
755
766
|
for (const [facet, ref] of refs) {
|
|
756
|
-
const id =
|
|
767
|
+
const id = _chunkHRUK5TFWcjs.brushSourceIdOf.call(void 0, ref);
|
|
757
768
|
if (id === null || await library.getSource(id)) continue;
|
|
758
769
|
const ids = (await library.listSources()).map((x) => x.id);
|
|
759
|
-
issues.push({ facet, severity: "error", reason: `There is no image source "${id}" in the brush library. ${
|
|
770
|
+
issues.push({ facet, severity: "error", reason: `There is no image source "${id}" in the brush library. ${_chunkHRUK5TFWcjs.closest.call(void 0, id, ids)}`.trim(), fix: "Add it with add_brush_source, or use a ref list_brush_sources lists." });
|
|
760
771
|
}
|
|
761
|
-
const provider = _optionalChain([options, 'access',
|
|
772
|
+
const provider = _optionalChain([options, 'access', _26 => _26.stickers, 'optionalCall', _27 => _27()]);
|
|
762
773
|
if (!provider || brush.tip.shape !== "stamp") return { ok: !issues.some((i) => i.severity === "error"), issues };
|
|
763
774
|
for (const ref of _nullishCoalesce(brush.tip.stamps, () => ( []))) {
|
|
764
|
-
if (ref.startsWith("editor:") ||
|
|
775
|
+
if (ref.startsWith("editor:") || _chunkHRUK5TFWcjs.isBrushSourceRef.call(void 0, ref)) continue;
|
|
765
776
|
try {
|
|
766
777
|
await _chunkPFHJS4HEcjs.describeStickerRef.call(void 0, provider, ref);
|
|
767
778
|
} catch (e) {
|
|
@@ -774,12 +785,12 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
774
785
|
const problems = [];
|
|
775
786
|
let brush;
|
|
776
787
|
try {
|
|
777
|
-
brush =
|
|
788
|
+
brush = _chunkHRUK5TFWcjs.normalizeBrushSpec.call(void 0, raw, problems);
|
|
778
789
|
} catch (e) {
|
|
779
|
-
throw new (0,
|
|
790
|
+
throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("invalid", e.message);
|
|
780
791
|
}
|
|
781
|
-
const check2 =
|
|
782
|
-
if (!check2.ok) throw new (0,
|
|
792
|
+
const check2 = _chunkHRUK5TFWcjs.withKeptIssues.call(void 0, await checkFor(brush, profile), original ? await checkFor(original, profile) : null);
|
|
793
|
+
if (!check2.ok) throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("invalid", refusal(check2, profile));
|
|
783
794
|
const saved = await library.save(brush, { overwrite });
|
|
784
795
|
return { ...saved, problems, check: check2 };
|
|
785
796
|
};
|
|
@@ -790,10 +801,10 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
790
801
|
inputSchema: {
|
|
791
802
|
type: "object",
|
|
792
803
|
properties: {
|
|
793
|
-
kind: { type: "string", enum: [...
|
|
794
|
-
medium: { type: "string", enum: [...
|
|
804
|
+
kind: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_KINDS], description: "mark (lays a material) or tool (works on paint already down)." },
|
|
805
|
+
medium: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_MEDIA], description: "Marks laying this medium." },
|
|
795
806
|
variety: { type: "string", maxLength: 40, description: "This variety (oil, watercolor, pencil, highlighter\u2026)." },
|
|
796
|
-
tool: { type: "string", enum: [...
|
|
807
|
+
tool: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_TOOLS], description: "Tools that do this." },
|
|
797
808
|
tag: { type: "string", maxLength: 40, description: "Brushes with this tag." },
|
|
798
809
|
text: { type: "string", maxLength: 200, description: "Words in the id, name, description, variety or tags (each word must match the start of one)." },
|
|
799
810
|
source: { type: "string", enum: ["all", "builtin", "user"], description: "all (default), builtin presets only, or user (saved) brushes only." },
|
|
@@ -820,8 +831,8 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
820
831
|
annotations: { title: "Describe a brush", ...READ },
|
|
821
832
|
handler: async ({ id }) => {
|
|
822
833
|
const e = await entry(id);
|
|
823
|
-
const engine =
|
|
824
|
-
return { brush: e.brush, builtin: e.builtin, engine, category:
|
|
834
|
+
const engine = _chunkHRUK5TFWcjs.resolveEngine.call(void 0, e.brush);
|
|
835
|
+
return { brush: e.brush, builtin: e.builtin, engine, category: _chunkHRUK5TFWcjs.resolveCategory.call(void 0, e.brush, engine), check: await checkFor(e.brush, profile) };
|
|
825
836
|
}
|
|
826
837
|
};
|
|
827
838
|
const check = {
|
|
@@ -839,20 +850,20 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
839
850
|
},
|
|
840
851
|
annotations: { title: "Check a brush for a host", ...READ },
|
|
841
852
|
handler: async ({ id, brush, host }) => {
|
|
842
|
-
if (id === void 0 === (brush === void 0)) throw new (0,
|
|
853
|
+
if (id === void 0 === (brush === void 0)) throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("invalid", "Give either id (a library brush) or brush (a spec), not both or neither.");
|
|
843
854
|
const p = hostOf(host);
|
|
844
855
|
let b;
|
|
845
856
|
const problems = [];
|
|
846
857
|
if (id !== void 0) b = (await entry(id)).brush;
|
|
847
858
|
else {
|
|
848
859
|
try {
|
|
849
|
-
b =
|
|
860
|
+
b = _chunkHRUK5TFWcjs.normalizeBrushSpec.call(void 0, brush, problems);
|
|
850
861
|
} catch (e) {
|
|
851
|
-
throw new (0,
|
|
862
|
+
throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("invalid", e.message);
|
|
852
863
|
}
|
|
853
864
|
}
|
|
854
865
|
const result = await checkFor(b, p);
|
|
855
|
-
return { host: p.id, ...result, ...problems.length ? { problems } : {}, ...!result.ok ? { degraded:
|
|
866
|
+
return { host: p.id, ...result, ...problems.length ? { problems } : {}, ...!result.ok ? { degraded: _chunkHRUK5TFWcjs.degrade.call(void 0, b, p) } : {} };
|
|
856
867
|
}
|
|
857
868
|
};
|
|
858
869
|
const exportTool = {
|
|
@@ -887,7 +898,7 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
887
898
|
});
|
|
888
899
|
const start = _nullishCoalesce(offset, () => ( 0));
|
|
889
900
|
const page = found.slice(start, start + (_nullishCoalesce(limit, () => ( 100))));
|
|
890
|
-
return { total: found.length, sources: page.map((x) => ({ ...
|
|
901
|
+
return { total: found.length, sources: page.map((x) => ({ ..._chunkHRUK5TFWcjs.summarizeBrushSource.call(void 0, x), usedBy: brushes.filter((b) => _chunkHRUK5TFWcjs.brushSourceIds.call(void 0, b).includes(x.id)).map((b) => b.id) })) };
|
|
891
902
|
}
|
|
892
903
|
};
|
|
893
904
|
const tools = [list, describe, check, exportTool, listSources];
|
|
@@ -911,7 +922,7 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
911
922
|
annotations: { title: "Preview a brush", ...READ },
|
|
912
923
|
handler: async ({ id, width, height, color }) => {
|
|
913
924
|
const { brush } = await entry(id);
|
|
914
|
-
const own = typeof _optionalChain([brush, 'access',
|
|
925
|
+
const own = typeof _optionalChain([brush, 'access', _28 => _28.colour, 'optionalAccess', _29 => _29.default]) === "string" && /^#[0-9a-f]{6}/i.test(brush.colour.default) ? brush.colour.default.slice(0, 7) : void 0;
|
|
915
926
|
const w = _nullishCoalesce(width, () => ( 256));
|
|
916
927
|
const h = _nullishCoalesce(height, () => ( 96));
|
|
917
928
|
const image = await render(brush, { width: w, height: h, color: _nullishCoalesce(_nullishCoalesce(color, () => ( own)), () => ( "#1f2937")) });
|
|
@@ -938,12 +949,12 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
938
949
|
},
|
|
939
950
|
annotations: { title: "Save a new brush", ...WRITE },
|
|
940
951
|
handler: async ({ basedOn, ...spec }) => {
|
|
941
|
-
if (library.isBuiltin(spec.id)) throw new (0,
|
|
942
|
-
if (await library.get(spec.id)) throw new (0,
|
|
952
|
+
if (library.isBuiltin(spec.id)) throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("builtin", `"${spec.id}" is a built-in brush id; pick another id (or basedOn "${spec.id}" with a new id).`);
|
|
953
|
+
if (await library.get(spec.id)) throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("exists", `A brush "${spec.id}" exists already; pick another id, or change it with update_brush.`);
|
|
943
954
|
const base = basedOn !== void 0 ? (await entry(basedOn)).brush : void 0;
|
|
944
955
|
const raw = base ? merge(base, spec) : spec;
|
|
945
956
|
const saved = await store(raw, false);
|
|
946
|
-
return { id: saved.brush.id, brush: saved.brush, engine:
|
|
957
|
+
return { id: saved.brush.id, brush: saved.brush, engine: _chunkHRUK5TFWcjs.resolveEngine.call(void 0, saved.brush), problems: saved.problems, warnings: warnings(saved.check) };
|
|
947
958
|
}
|
|
948
959
|
},
|
|
949
960
|
{
|
|
@@ -964,7 +975,7 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
964
975
|
annotations: { title: "Update a brush", ...WRITE, idempotentHint: true },
|
|
965
976
|
handler: async ({ id, unset, ...patch }) => {
|
|
966
977
|
const e = await entry(id);
|
|
967
|
-
if (e.builtin) throw new (0,
|
|
978
|
+
if (e.builtin) throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("builtin", `"${id}" is a built-in brush and can't be changed; duplicate_brush makes a copy you can change.`);
|
|
968
979
|
const base = copy2(e.brush);
|
|
969
980
|
for (const k of _nullishCoalesce(unset, () => ( []))) delete base[k];
|
|
970
981
|
const saved = await store(merge(base, { ...patch, id }), true, e.brush);
|
|
@@ -974,14 +985,14 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
974
985
|
{
|
|
975
986
|
name: "add_brush_source",
|
|
976
987
|
title: "Add a brush image source",
|
|
977
|
-
description: `Adds an image to the brush library as a source for image tips and image grain (as Procreate's shape and grain sources). The image is a PNG data: URL; the marks are read from its transparency, its dark parts (a scan of marks on paper) or its light parts (white on black), as channel says, and kept as a grey mask at most ${
|
|
988
|
+
description: `Adds an image to the brush library as a source for image tips and image grain (as Procreate's shape and grain sources). The image is a PNG data: URL; the marks are read from its transparency, its dark parts (a scan of marks on paper) or its light parts (white on black), as channel says, and kept as a grey mask at most ${_chunkHRUK5TFWcjs.MAX_BRUSH_SOURCE_SIZE} px on a side. Returns id, ref (source:<id>), the stored source's width and height, problems (the channel auto picked, scaling) and replaced. Then make the brush: create_brush or update_brush with tip { shape: "stamp", stamps: [ref] } for an image tip, or tip.grain { source: ref } for grain. A taken id is refused unless overwrite.`,
|
|
978
989
|
inputSchema: {
|
|
979
990
|
type: "object",
|
|
980
991
|
properties: {
|
|
981
992
|
name: { type: "string", minLength: 1, maxLength: 80, description: 'Display name, e.g. "Charcoal scan".' },
|
|
982
|
-
image: { type: "string", pattern: "^data:image/png;base64,", maxLength: 4e7, description: `The image: a PNG data: URL, at most ${
|
|
993
|
+
image: { type: "string", pattern: "^data:image/png;base64,", maxLength: 4e7, description: `The image: a PNG data: URL, at most ${_chunkHRUK5TFWcjs.MAX_BRUSH_SOURCE_INPUT_PIXELS} pixels; larger than ${_chunkHRUK5TFWcjs.MAX_BRUSH_SOURCE_SIZE} px it is scaled down.` },
|
|
983
994
|
id: { type: "string", pattern: String(FACETS2.id.pattern), description: "The source id (default: from the name, made unique): lowercase letters, digits and dashes." },
|
|
984
|
-
channel: { type: "string", enum: [...
|
|
995
|
+
channel: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_SOURCE_CHANNELS], description: "Where the marks are: auto (default: the transparency when the image has any, else the dark parts), alpha, darkness (dark marks on light paper) or lightness (light marks on black)." },
|
|
985
996
|
invert: { type: "boolean", description: "Swap painted and empty parts (default false)." },
|
|
986
997
|
licence: { type: "string", maxLength: 2e3, description: "The licence or terms the image came with, kept with the source." },
|
|
987
998
|
origin: { type: "string", maxLength: 200, description: "Where it came from: a file name, a pack or a URL." },
|
|
@@ -993,7 +1004,7 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
993
1004
|
annotations: { title: "Add a brush image source", ...WRITE },
|
|
994
1005
|
handler: async ({ overwrite, ...input }) => {
|
|
995
1006
|
const r = await library.addSource(input, { overwrite: !!overwrite });
|
|
996
|
-
return { id: r.source.id, ref:
|
|
1007
|
+
return { id: r.source.id, ref: _chunkHRUK5TFWcjs.brushSourceRef.call(void 0, r.source.id), width: r.source.width, height: r.source.height, problems: r.problems, replaced: r.replaced };
|
|
997
1008
|
}
|
|
998
1009
|
},
|
|
999
1010
|
{
|
|
@@ -1067,24 +1078,24 @@ function createBrushLibraryTools(library, options = {}) {
|
|
|
1067
1078
|
try {
|
|
1068
1079
|
bytes = _chunkW5M3J7PVcjs.base64ToBytes.call(void 0, file.replace(/^data:[^,]*,/, ""));
|
|
1069
1080
|
} catch (e6) {
|
|
1070
|
-
throw new (0,
|
|
1081
|
+
throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("invalid", "file is not base64: pass the pack's bytes as base64 (a data: URL works too).");
|
|
1071
1082
|
}
|
|
1072
1083
|
let r;
|
|
1073
1084
|
try {
|
|
1074
1085
|
r = await importBrushPack(library, bytes, { fileName, ...format ? { format } : {}, ...prefix ? { prefix } : {}, ...licence ? { licence } : {}, overwrite: !!overwrite });
|
|
1075
1086
|
} catch (e) {
|
|
1076
|
-
if (e instanceof
|
|
1077
|
-
throw new (0,
|
|
1087
|
+
if (e instanceof _chunkHRUK5TFWcjs.BrushLibraryError) throw e;
|
|
1088
|
+
throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("invalid", `${e.message} Nothing was imported.`);
|
|
1078
1089
|
}
|
|
1079
1090
|
const entries = await Promise.all(r.brushes.map((b) => library.get(b.id)));
|
|
1080
|
-
return { ...r, brushes: r.brushes.map((b, i) => ({ ...b, renderable: entries[i] ?
|
|
1091
|
+
return { ...r, brushes: r.brushes.map((b, i) => ({ ...b, renderable: entries[i] ? _chunkHRUK5TFWcjs.checkBrush.call(void 0, entries[i].brush, profile).ok : false })) };
|
|
1081
1092
|
}
|
|
1082
1093
|
}
|
|
1083
1094
|
);
|
|
1084
1095
|
return tools;
|
|
1085
1096
|
}
|
|
1086
1097
|
function createBrushLibraryToolProvider(library, options = {}) {
|
|
1087
|
-
const profile = _nullishCoalesce(options.profile, () => (
|
|
1098
|
+
const profile = _nullishCoalesce(options.profile, () => ( _chunkHRUK5TFWcjs.PAINT_PROFILE));
|
|
1088
1099
|
const tools = createBrushLibraryTools(library, options);
|
|
1089
1100
|
return {
|
|
1090
1101
|
id: _nullishCoalesce(options.id, () => ( "brushes")),
|
|
@@ -1135,7 +1146,7 @@ function brushEngineControls(brush) {
|
|
|
1135
1146
|
const c = engineControls(brush);
|
|
1136
1147
|
if (!c) return null;
|
|
1137
1148
|
const mut = brush.mutation ? MUTATION_SLIDERS : [];
|
|
1138
|
-
const wetPaint = brush.engine === "wet" && _optionalChain([brush, 'access',
|
|
1149
|
+
const wetPaint = brush.engine === "wet" && _optionalChain([brush, 'access', _30 => _30.wet, 'optionalAccess', _31 => _31.tool]) === "paint" && !brush.ghost && !brush.mutation;
|
|
1139
1150
|
if (!(wetPaint || ["dab", "mixer", "particle", "bristle", "impasto"].includes(brush.engine))) {
|
|
1140
1151
|
return mut.length ? { ...c, sliders: [...c.sliders, ...mut] } : c;
|
|
1141
1152
|
}
|
|
@@ -1221,7 +1232,7 @@ function engineControls(brush) {
|
|
|
1221
1232
|
impastoTool: true
|
|
1222
1233
|
};
|
|
1223
1234
|
case "wet": {
|
|
1224
|
-
const tool = _nullishCoalesce(_optionalChain([brush, 'access',
|
|
1235
|
+
const tool = _nullishCoalesce(_optionalChain([brush, 'access', _32 => _32.wet, 'optionalAccess', _33 => _33.tool]), () => ( "paint"));
|
|
1225
1236
|
const ghost = tool === "paint" && (Boolean(brush.ghost) || Boolean(brush.mutation));
|
|
1226
1237
|
const sliders = tool === "paint" ? [
|
|
1227
1238
|
{ path: "wet.water", label: "Water", min: 0, max: 1, step: 0.01 },
|