@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
package/dist/brushes/index.cjs
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
var
|
|
21
|
+
var _chunkJVFGK3DKcjs = require('../chunk-JVFGK3DK.cjs');
|
|
22
22
|
require('../chunk-PFHJS4HE.cjs');
|
|
23
23
|
|
|
24
24
|
|
|
@@ -27,7 +27,7 @@ require('../chunk-PFHJS4HE.cjs');
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
var
|
|
30
|
+
var _chunkH3EME3S5cjs = require('../chunk-H3EME3S5.cjs');
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
@@ -102,7 +102,7 @@ var _chunkJDXWLCXFcjs = require('../chunk-JDXWLCXF.cjs');
|
|
|
102
102
|
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
var
|
|
105
|
+
var _chunkHRUK5TFWcjs = require('../chunk-HRUK5TFW.cjs');
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
var _chunkRDFHWAHLcjs = require('../chunk-RDFHWAHL.cjs');
|
|
@@ -113,7 +113,8 @@ require('../chunk-U67EN7GG.cjs');
|
|
|
113
113
|
require('../chunk-WOFXZ3XU.cjs');
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
|
|
117
|
+
var _chunkIFWLZZCWcjs = require('../chunk-IFWLZZCW.cjs');
|
|
117
118
|
require('../chunk-3K6HWEXZ.cjs');
|
|
118
119
|
|
|
119
120
|
|
|
@@ -162,23 +163,24 @@ var ARIA = {
|
|
|
162
163
|
"behaviour.thick.applicator": "Impasto tool",
|
|
163
164
|
"light.pressure": "Light follows pressure",
|
|
164
165
|
"tip.grain.source": "Tip grain",
|
|
165
|
-
"dynamics.angleJitter": "Brush rotation jitter"
|
|
166
|
+
"dynamics.angleJitter": "Brush rotation jitter",
|
|
167
|
+
"livePatterns.pattern": "Live pattern"
|
|
166
168
|
};
|
|
167
169
|
var aria = (path, label) => _nullishCoalesce(ARIA[path], () => ( `Brush ${label.toLowerCase()}`));
|
|
168
|
-
function brushEditorSections(brush, profile =
|
|
169
|
-
const resolved =
|
|
170
|
-
const engine =
|
|
171
|
-
const fieldOf = (facet) =>
|
|
172
|
-
const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(
|
|
170
|
+
function brushEditorSections(brush, profile = _chunkHRUK5TFWcjs.PAINT_PROFILE, context = {}) {
|
|
171
|
+
const resolved = _chunkHRUK5TFWcjs.resolveBrush.call(void 0, brush);
|
|
172
|
+
const engine = _chunkHRUK5TFWcjs.resolveEngine.call(void 0, brush);
|
|
173
|
+
const fieldOf = (facet) => _chunkHRUK5TFWcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
|
|
174
|
+
const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkHRUK5TFWcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkHRUK5TFWcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
|
|
173
175
|
const value = (path) => {
|
|
174
|
-
const own =
|
|
176
|
+
const own = _chunkHRUK5TFWcjs.getPath.call(void 0, brush, path);
|
|
175
177
|
if (own !== void 0) return own;
|
|
176
178
|
const field = fieldOf(path);
|
|
177
179
|
if (!field) return void 0;
|
|
178
|
-
const v =
|
|
180
|
+
const v = _chunkHRUK5TFWcjs.getPath.call(void 0, resolved, field.engine);
|
|
179
181
|
return field.map ? field.map.toFacet(v) : v;
|
|
180
182
|
};
|
|
181
|
-
const issues =
|
|
183
|
+
const issues = _chunkHRUK5TFWcjs.checkBrush.call(void 0, brush, profile).issues;
|
|
182
184
|
const warned = new Map(issues.filter((i) => i.severity === "warning").map((i) => [i.facet, i.reason]));
|
|
183
185
|
const refused = new Set(issues.filter((i) => i.severity === "error").map((i) => i.facet));
|
|
184
186
|
const full = (s) => s === "full";
|
|
@@ -191,7 +193,7 @@ function brushEditorSections(brush, profile = _chunk6QNDGMK7cjs.PAINT_PROFILE, c
|
|
|
191
193
|
const slider = (c, path = facetOf(c.path)) => {
|
|
192
194
|
if (!path) return null;
|
|
193
195
|
const v = value(path);
|
|
194
|
-
return withNote({ kind: "slider", path, label: c.label, ariaLabel: aria(path, c.label), min: c.min, max: path === "tip.size" ? Math.min(c.max,
|
|
196
|
+
return withNote({ kind: "slider", path, label: c.label, ariaLabel: aria(path, c.label), min: c.min, max: path === "tip.size" ? Math.min(c.max, _chunkIFWLZZCWcjs.MAX_BRUSH_SIZE) : c.max, step: c.step, value: typeof v === "number" ? v : c.min });
|
|
195
197
|
};
|
|
196
198
|
const choice = (path, label, opts, fallback = _nullishCoalesce(_optionalChain([opts, 'access', _5 => _5[0], 'optionalAccess', _6 => _6.value]), () => ( ""))) => withNote({ kind: "choice", path, label, ariaLabel: aria(path, label), options: opts, value: String(_nullishCoalesce(value(path), () => ( fallback))) });
|
|
197
199
|
const toggle = (path, label) => withNote({ kind: "toggle", path, label, ariaLabel: aria(path, label), value: Boolean(value(path)) });
|
|
@@ -203,30 +205,30 @@ function brushEditorSections(brush, profile = _chunk6QNDGMK7cjs.PAINT_PROFILE, c
|
|
|
203
205
|
};
|
|
204
206
|
const isTool = brush.kind === "tool";
|
|
205
207
|
const shape = brush.tip.shape;
|
|
206
|
-
const sourceOptions = (_nullishCoalesce(context.sources, () => ( []))).map((x) => ({ value:
|
|
208
|
+
const sourceOptions = (_nullishCoalesce(context.sources, () => ( []))).map((x) => ({ value: _chunkHRUK5TFWcjs.brushSourceRef.call(void 0, x.id), label: x.name }));
|
|
207
209
|
const marks = _nullishCoalesce(_optionalChain([brush, 'access', _7 => _7.marks, 'optionalAccess', _8 => _8.kind]), () => ( "continuous"));
|
|
208
210
|
const exchangeFull = full(_optionalChain([brush, 'access', _9 => _9.behaviour, 'optionalAccess', _10 => _10.exchange, 'optionalAccess', _11 => _11.reservoir]) ? profile.reservoir : profile.exchange);
|
|
209
211
|
add("medium", "Medium", [
|
|
210
212
|
profile.kinds.length > 1 && profile.kinds.includes(brush.kind) && choice("kind", "Kind", options(profile.kinds, { mark: "Lays a material", tool: "Works on paint" })),
|
|
211
|
-
!isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(
|
|
213
|
+
!isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkHRUK5TFWcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
|
|
212
214
|
!isTool && withNote({ kind: "text", path: "variety", label: "Variety", ariaLabel: "Brush variety", value: _nullishCoalesce(brush.variety, () => ( "")), placeholder: "pencil, oil, highlighter\u2026" }),
|
|
213
215
|
isTool && !!brush.tool && profile.tools.includes(brush.tool) && choice("tool", "Tool", options(profile.tools, TOOL_LABELS))
|
|
214
216
|
]);
|
|
215
|
-
const engineControls =
|
|
216
|
-
const tipSliders =
|
|
217
|
+
const engineControls = _chunkJVFGK3DKcjs.brushEngineControls.call(void 0, resolved);
|
|
218
|
+
const tipSliders = _chunkJVFGK3DKcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
|
|
217
219
|
add("shape", "Shape", [
|
|
218
220
|
!refused.has("tip.shape") && choice("tip.shape", "Tip", options(profile.tipShapes.filter((s) => !isTool || s !== "stamp"), SHAPE_LABELS)),
|
|
219
221
|
...tipSliders.map((c) => slider(c)),
|
|
220
222
|
engine === "dab" && choice("tip.blend", "Blend", _chunk2VX55NFMcjs.BLEND_MODES.map((m) => ({ value: m.id, label: m.label })), "normal"),
|
|
221
223
|
...shape === "bristle" && engineOk && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("bristle.")).map((c) => slider(c)) : [],
|
|
222
|
-
shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ?
|
|
224
|
+
shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunkHRUK5TFWcjs.MAX_DOT_TEXTURES : _chunkHRUK5TFWcjs.MAX_STICKER_STAMPS, options: marks === "objects" ? STAMP_OPTIONS : [...STAMP_OPTIONS, ...sourceOptions] })
|
|
223
225
|
]);
|
|
224
226
|
const dabs = DAB_ENGINES.has(engine) && engineOk && shape !== "bristle" && marks !== "particles" && marks !== "objects";
|
|
225
227
|
const grain = brush.tip.grain;
|
|
226
228
|
if (dabs && full(_nullishCoalesce(profile.tipGrain, () => ( "none")))) {
|
|
227
229
|
add("grain", "Tip grain", [
|
|
228
|
-
choice("tip.grain.source", "Texture", [{ value: "", label: "None" }, ...options(
|
|
229
|
-
!!grain && choice("tip.grain.mode", "Grain moves", options(
|
|
230
|
+
choice("tip.grain.source", "Texture", [{ value: "", label: "None" }, ...options(_chunkHRUK5TFWcjs.TIP_GRAIN_PATTERNS), ...sourceOptions], ""),
|
|
231
|
+
!!grain && choice("tip.grain.mode", "Grain moves", options(_chunkHRUK5TFWcjs.BRUSH_GRAIN_MODES, GRAIN_MODE_LABELS), "texturised"),
|
|
230
232
|
!!grain && withNote({ kind: "slider", path: "tip.grain.scale", label: "Grain scale", ariaLabel: "Brush grain scale", min: 0.1, max: 8, step: 0.05, value: _nullishCoalesce(grain.scale, () => ( 1)) }),
|
|
231
233
|
!!grain && withNote({ kind: "slider", path: "tip.grain.depth", label: "Grain depth", ariaLabel: "Brush grain depth", min: 0, max: 1, step: 0.01, value: _nullishCoalesce(grain.depth, () => ( 0.6)) }),
|
|
232
234
|
!!grain && withNote({ kind: "slider", path: "tip.grain.contrast", label: "Grain contrast", ariaLabel: "Brush grain contrast", min: 0, max: 3, step: 0.05, value: _nullishCoalesce(grain.contrast, () => ( 1)) }),
|
|
@@ -239,28 +241,28 @@ function brushEditorSections(brush, profile = _chunk6QNDGMK7cjs.PAINT_PROFILE, c
|
|
|
239
241
|
const render = value("marks.render");
|
|
240
242
|
add("marks", "Marks", [
|
|
241
243
|
choice("marks.kind", "Laid as", options(profile.marks, MARKS_LABELS), "continuous"),
|
|
242
|
-
marks === "particles" && choice("marks.physics", "Particles", options(
|
|
243
|
-
marks === "particles" && choice("marks.render", "Drawn as", options(
|
|
244
|
-
marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(
|
|
245
|
-
marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(
|
|
246
|
-
marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(
|
|
244
|
+
marks === "particles" && choice("marks.physics", "Particles", options(_chunkHRUK5TFWcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
|
|
245
|
+
marks === "particles" && choice("marks.render", "Drawn as", options(_chunkHRUK5TFWcjs.PARTICLE_RENDERS, RENDER_LABELS)),
|
|
246
|
+
marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkHRUK5TFWcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
|
|
247
|
+
marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkHRUK5TFWcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
|
|
248
|
+
marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkHRUK5TFWcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
|
|
247
249
|
...particles.map((c) => slider(c)),
|
|
248
250
|
...objects.map((c) => slider(c))
|
|
249
251
|
]);
|
|
250
252
|
}
|
|
251
|
-
const feel =
|
|
253
|
+
const feel = _chunkJVFGK3DKcjs.BRUSH_SLIDERS.filter((c) => ["tip.smoothing", "pressureSmoothing", "dynamics.minSize", "dynamics.tiltSize", "dynamics.velocitySize"].includes(c.path)).filter((c) => !(c.path === "dynamics.tiltSize" && !full(profile.tilt)) && !(c.path === "dynamics.velocitySize" && !full(profile.velocity)));
|
|
252
254
|
const stampDabs = dabs && shape === "stamp";
|
|
253
255
|
const jitter = (path, label, max = 1, step = 0.01) => withNote({ kind: "slider", path, label, ariaLabel: aria(path, label), min: 0, max, step, value: Number(_nullishCoalesce(value(path), () => ( 0))) });
|
|
254
256
|
add("feel", "Feel", [
|
|
255
257
|
...feel.map((c) => slider(c)),
|
|
256
258
|
toggle("dynamics.pressureSize", "Pressure \u2192 size"),
|
|
257
259
|
toggle("dynamics.pressureOpacity", "Pressure \u2192 opacity"),
|
|
258
|
-
choice("dynamics.rotation", "Rotation", options(
|
|
260
|
+
choice("dynamics.rotation", "Rotation", options(_chunkHRUK5TFWcjs.BRUSH_ROTATIONS, ROTATION_LABELS)),
|
|
259
261
|
stampDabs && full(_nullishCoalesce(profile.dabCount, () => ( "none"))) && withNote({ kind: "slider", path: "dynamics.count", label: "Count", ariaLabel: "Brush dab count", min: 1, max: 16, step: 1, value: _nullishCoalesce(_optionalChain([brush, 'access', _12 => _12.dynamics, 'optionalAccess', _13 => _13.count]), () => ( 1)) }),
|
|
260
262
|
stampDabs && jitter("dynamics.scatter", "Scatter", 4),
|
|
261
263
|
stampDabs && jitter("dynamics.angleJitter", "Rotation jitter"),
|
|
262
264
|
stampDabs && jitter("dynamics.sizeJitter", "Size jitter"),
|
|
263
|
-
stampDabs && choice("dynamics.flip", "Flip", options(
|
|
265
|
+
stampDabs && choice("dynamics.flip", "Flip", options(_chunkHRUK5TFWcjs.BRUSH_FLIPS, FLIP_LABELS), "none")
|
|
264
266
|
]);
|
|
265
267
|
const surfaces = profile.surfaces;
|
|
266
268
|
const engineSliders = (engineOk ? _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _14 => _14.sliders]), () => ( [])) : []).filter((c) => !/^(bristle|particle|sticker|iridescence)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
|
|
@@ -268,12 +270,16 @@ function brushEditorSections(brush, profile = _chunk6QNDGMK7cjs.PAINT_PROFILE, c
|
|
|
268
270
|
add("behaviour", _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _17 => _17.title]), () => ( "Behaviour")), [
|
|
269
271
|
!isTool && surfaces.length > 1 && !refused.has("behaviour.surface") && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
|
|
270
272
|
full(profile.grain) && slider({ path: "grain", label: "Grain", min: 0, max: 1, step: 0.01 }, "behaviour.grain"),
|
|
271
|
-
engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(
|
|
272
|
-
engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(
|
|
273
|
+
engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunkHRUK5TFWcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
|
|
274
|
+
engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunkHRUK5TFWcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
|
|
273
275
|
...engineSliders.map((c) => exchangeOk(facetOf(c.path)) ? slider(c) : null),
|
|
274
276
|
engineOk && _optionalChain([engineControls, 'optionalAccess', _18 => _18.mixingPath]) && (engine === "wet" || exchangeFull) && fieldOf("behaviour.mixing") && choice("behaviour.mixing", "Mixing", options(["pigment", "rgb"], { pigment: "Pigment", rgb: "RGB" })),
|
|
275
277
|
engineOk && _optionalChain([engineControls, 'optionalAccess', _19 => _19.dirty]) && exchangeFull && fieldOf("behaviour.exchange.dirty") && toggle("behaviour.exchange.dirty", "Dirty brush"),
|
|
276
|
-
engine === "mixer" && engineOk && full(profile.reservoir) && toggle("behaviour.exchange.reservoir.refill", "Load each stroke")
|
|
278
|
+
engine === "mixer" && engineOk && full(profile.reservoir) && toggle("behaviour.exchange.reservoir.refill", "Load each stroke"),
|
|
279
|
+
engine === "wet" && engineOk && !isTool && full(_nullishCoalesce(profile.livePatterns, () => ( "none"))) && choice("livePatterns.pattern", "Live pattern", [{ value: "", label: "None" }, ...options(_chunkIFWLZZCWcjs.LIVE_PATTERN_KINDS)], ""),
|
|
280
|
+
engine === "wet" && engineOk && !isTool && full(_nullishCoalesce(profile.livePatterns, () => ( "none"))) && !!brush.livePatterns && withNote({ kind: "slider", path: "livePatterns.scale", label: "Pattern scale", ariaLabel: "Brush pattern scale", min: 0.5, max: 4, step: 0.1, value: _nullishCoalesce(brush.livePatterns.scale, () => ( 1)) }),
|
|
281
|
+
engine === "wet" && engineOk && !isTool && full(_nullishCoalesce(profile.livePatterns, () => ( "none"))) && !!brush.livePatterns && withNote({ kind: "slider", path: "livePatterns.contrast", label: "Pattern contrast", ariaLabel: "Brush pattern contrast", min: 0, max: 2, step: 0.05, value: _nullishCoalesce(brush.livePatterns.contrast, () => ( 1)) }),
|
|
282
|
+
engine === "wet" && engineOk && !isTool && full(_nullishCoalesce(profile.livePatterns, () => ( "none"))) && !!brush.livePatterns && withNote({ kind: "slider", path: "livePatterns.relief", label: "Pattern relief", ariaLabel: "Brush pattern relief", min: 0, max: 1, step: 0.05, value: _nullishCoalesce(brush.livePatterns.relief, () => ( 0)) })
|
|
277
283
|
]);
|
|
278
284
|
if (!isTool && full(profile.light) && engineOk && _optionalChain([engineControls, 'optionalAccess', _20 => _20.light])) {
|
|
279
285
|
add("light", "Light", [
|
|
@@ -307,7 +313,7 @@ function brushEditorSections(brush, profile = _chunk6QNDGMK7cjs.PAINT_PROFILE, c
|
|
|
307
313
|
label: "Palette",
|
|
308
314
|
ariaLabel: "Brush palette",
|
|
309
315
|
value: (_nullishCoalesce(_optionalChain([brush, 'access', _32 => _32.colour, 'optionalAccess', _33 => _33.palette]), () => ( []))).flatMap((c) => _chunkMLLTWAXHcjs.isDualColor.call(void 0, c) ? [{ light: _chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "light"), dark: _chunkJBZRVLXVcjs.brushColourHex.call(void 0, c, "dark") }] : hex(c) ? [hex(c)] : []),
|
|
310
|
-
max:
|
|
316
|
+
max: _chunkHRUK5TFWcjs.MAX_BRUSH_PALETTE
|
|
311
317
|
}),
|
|
312
318
|
toggle("colour.own", "Always its own colour")
|
|
313
319
|
]);
|
|
@@ -338,6 +344,8 @@ function hiddenLabel(issue, b) {
|
|
|
338
344
|
return "several dabs per step";
|
|
339
345
|
case "light":
|
|
340
346
|
return "light";
|
|
347
|
+
case "livePatterns":
|
|
348
|
+
return "live patterns";
|
|
341
349
|
case "fluorescence":
|
|
342
350
|
return "UV-fluorescent ink";
|
|
343
351
|
case "thermochromic":
|
|
@@ -355,15 +363,15 @@ function hiddenLabel(issue, b) {
|
|
|
355
363
|
case "dynamics.tilt":
|
|
356
364
|
return "tilt dynamics";
|
|
357
365
|
case "colour.default":
|
|
358
|
-
return `a ${
|
|
366
|
+
return `a ${_chunkHRUK5TFWcjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
|
|
359
367
|
default:
|
|
360
368
|
return null;
|
|
361
369
|
}
|
|
362
370
|
}
|
|
363
371
|
var sentence = (words) => words.length < 2 ? _nullishCoalesce(words[0], () => ( "")) : `${words.slice(0, -1).join(", ")} and ${words.at(-1)}`;
|
|
364
|
-
function brushEditorScope(brush, profile =
|
|
372
|
+
function brushEditorScope(brush, profile = _chunkHRUK5TFWcjs.PAINT_PROFILE) {
|
|
365
373
|
const hidden = [];
|
|
366
|
-
for (const issue of
|
|
374
|
+
for (const issue of _chunkHRUK5TFWcjs.checkBrush.call(void 0, brush, profile).issues) {
|
|
367
375
|
const label = hiddenLabel(issue, brush);
|
|
368
376
|
if (label && !hidden.some((h) => h.label === label)) hidden.push({ facet: issue.facet, label });
|
|
369
377
|
}
|
|
@@ -376,17 +384,17 @@ function newBrushFor(profile, from, name = "New brush") {
|
|
|
376
384
|
const id = brushIdFromName(name);
|
|
377
385
|
const base = { id, name, kind: profile.kinds.includes("mark") ? "mark" : profile.kinds[0], ...profile.kinds.includes("mark") ? {} : { tool: profile.tools[0] }, tip: { shape: profile.tipShapes.includes("round") ? "round" : profile.tipShapes[0] } };
|
|
378
386
|
if (from) {
|
|
379
|
-
const stripped =
|
|
387
|
+
const stripped = _chunkHRUK5TFWcjs.degrade.call(void 0, from, profile, { ignored: true });
|
|
380
388
|
if (!stripped.issues.length) return { ...stripped.brush, id, name };
|
|
381
389
|
}
|
|
382
390
|
return base;
|
|
383
391
|
}
|
|
384
392
|
async function saveBrushEdit(library, options2) {
|
|
385
393
|
const { original, profile } = options2;
|
|
386
|
-
const check =
|
|
394
|
+
const check = _chunkHRUK5TFWcjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
|
|
387
395
|
if (!check.ok) {
|
|
388
396
|
const errors = check.issues.filter((i) => i.severity === "error").map((i) => `${i.facet}: ${i.reason} ${i.fix}`);
|
|
389
|
-
throw new (0,
|
|
397
|
+
throw new (0, _chunkHRUK5TFWcjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
|
|
390
398
|
}
|
|
391
399
|
const inPlace = !!original && options2.name === void 0 && !library.isBuiltin(original.id) && original.id === options2.brush.id && !!await library.get(original.id);
|
|
392
400
|
let brush = options2.brush;
|
|
@@ -413,6 +421,7 @@ function setBrushEditorValue(brush, path, value) {
|
|
|
413
421
|
delete next.iridescence;
|
|
414
422
|
delete next.ghost;
|
|
415
423
|
delete next.mutation;
|
|
424
|
+
delete next.ferro;
|
|
416
425
|
delete next.colour;
|
|
417
426
|
next.tool = _nullishCoalesce(next.tool, () => ( "eraser"));
|
|
418
427
|
if (next.tip.shape === "stamp") next.tip = { shape: "round", ...next.tip.size !== void 0 ? { size: next.tip.size } : {} };
|
|
@@ -427,18 +436,20 @@ function setBrushEditorValue(brush, path, value) {
|
|
|
427
436
|
else delete next.iridescence;
|
|
428
437
|
} else if (path === "tip.grain.source" && (value === void 0 || value === "")) {
|
|
429
438
|
delete next.tip.grain;
|
|
439
|
+
} else if (path === "livePatterns.pattern" && (value === void 0 || value === "")) {
|
|
440
|
+
delete next.livePatterns;
|
|
430
441
|
} else if (path === "tip.shape" && value !== "stamp") {
|
|
431
442
|
next.tip = { ...next.tip, shape: value, stamps: void 0 };
|
|
432
443
|
if (value !== "bristle") delete next.tip.bristle;
|
|
433
444
|
} else if (value === void 0 || value === "") {
|
|
434
445
|
const keys = path.split(".");
|
|
435
|
-
const parent =
|
|
446
|
+
const parent = _chunkHRUK5TFWcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
|
|
436
447
|
if (keys.length === 1) delete next[keys[0]];
|
|
437
448
|
else if (parent) delete parent[keys[keys.length - 1]];
|
|
438
|
-
} else
|
|
449
|
+
} else _chunkHRUK5TFWcjs.setPath.call(void 0, next, path, value);
|
|
439
450
|
const problems = [];
|
|
440
451
|
try {
|
|
441
|
-
return { brush:
|
|
452
|
+
return { brush: _chunkHRUK5TFWcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
|
|
442
453
|
} catch (e) {
|
|
443
454
|
return { brush, problems: [e.message] };
|
|
444
455
|
}
|
|
@@ -454,7 +465,7 @@ function brushLibraryGroups(entries, filter = {}) {
|
|
|
454
465
|
const text = words([b.id, b.name, _nullishCoalesce(b.variety, () => ( "")), _nullishCoalesce(b.medium, () => ( "")), _nullishCoalesce(b.tool, () => ( "")), ..._nullishCoalesce(b.tags, () => ( []))].join(" "));
|
|
455
466
|
if (!wanted.every((w) => text.some((t) => t.startsWith(w)))) continue;
|
|
456
467
|
}
|
|
457
|
-
if (filter.profile && !
|
|
468
|
+
if (filter.profile && !_chunkHRUK5TFWcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
|
|
458
469
|
const id = b.kind === "tool" ? "tools" : _nullishCoalesce(b.medium, () => ( "other"));
|
|
459
470
|
let g = groups.get(id);
|
|
460
471
|
if (!g) groups.set(id, g = { id, title: id === "tools" ? "Tools" : id === "other" ? "Other" : MEDIUM_LABELS[id], varieties: [] });
|
|
@@ -470,7 +481,7 @@ async function imageFileToPngDataUrl(file) {
|
|
|
470
481
|
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
471
482
|
if (_chunkW5M3J7PVcjs.isPng.call(void 0, bytes)) return `data:image/png;base64,${_chunkW5M3J7PVcjs.bytesToBase64.call(void 0, bytes)}`;
|
|
472
483
|
const g = globalThis;
|
|
473
|
-
if (!g.createImageBitmap || !g.OffscreenCanvas) throw new (0,
|
|
484
|
+
if (!g.createImageBitmap || !g.OffscreenCanvas) throw new (0, _chunkHRUK5TFWcjs.BrushSourceError)("Only PNG images can be read here; convert the image to PNG.");
|
|
474
485
|
const bitmap = await g.createImageBitmap(file);
|
|
475
486
|
const canvas = new g.OffscreenCanvas(bitmap.width, bitmap.height);
|
|
476
487
|
canvas.getContext("2d").drawImage(bitmap, 0, 0);
|
|
@@ -480,7 +491,7 @@ async function imageFileToPngDataUrl(file) {
|
|
|
480
491
|
async function addBrushSourceFromFile(library, file, options2 = {}) {
|
|
481
492
|
const name = (_nullishCoalesce(_nullishCoalesce(options2.name, () => ( _optionalChain([file, 'access', _38 => _38.name, 'optionalAccess', _39 => _39.replace, 'call', _40 => _40(/\.[a-z0-9]+$/i, "")]))), () => ( "Image"))).trim() || "Image";
|
|
482
493
|
const result = await library.addSource({ name, image: await imageFileToPngDataUrl(file), origin: file.name, ...options2.channel ? { channel: options2.channel } : {} });
|
|
483
|
-
return { ...result, ref:
|
|
494
|
+
return { ...result, ref: _chunkHRUK5TFWcjs.brushSourceRef.call(void 0, result.source.id) };
|
|
484
495
|
}
|
|
485
496
|
function withBrushSource(brush, ref, as) {
|
|
486
497
|
if (as === "grain") return setBrushEditorValue(brush, "tip.grain.source", ref);
|
|
@@ -498,11 +509,11 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
|
|
|
498
509
|
properties: {
|
|
499
510
|
id: { type: "string", description: "paint, image, canvas, vector\u2026" },
|
|
500
511
|
name: { type: "string", description: "Display name, used in messages." },
|
|
501
|
-
kinds: { type: "array", items: { type: "string", enum: [...
|
|
502
|
-
tools: { type: "array", items: { type: "string", enum: [...
|
|
503
|
-
tipShapes: { type: "array", items: { type: "string", enum: [...
|
|
504
|
-
marks: { type: "array", items: { type: "string", enum: [...
|
|
505
|
-
surfaces: { type: "array", items: { type: "string", enum: [...
|
|
512
|
+
kinds: { type: "array", items: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
|
|
513
|
+
tools: { type: "array", items: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
|
|
514
|
+
tipShapes: { type: "array", items: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
|
|
515
|
+
marks: { type: "array", items: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
|
|
516
|
+
surfaces: { type: "array", items: { type: "string", enum: [..._chunkHRUK5TFWcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
|
|
506
517
|
exchange: { ...SUPPORT, description: "Picking paint up and mixing it in." },
|
|
507
518
|
reservoir: { ...SUPPORT, description: "The Mixer Brush reservoir." },
|
|
508
519
|
grain: { ...SUPPORT, description: "Paper grain response." },
|
|
@@ -513,7 +524,9 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
|
|
|
513
524
|
tilt: { ...SUPPORT, description: "Tilt dynamics." },
|
|
514
525
|
tipGrain: { ...SUPPORT, description: "Texture inside the tip (tip.grain); missing: none." },
|
|
515
526
|
dabCount: { ...SUPPORT, description: "Several dabs per spacing step (dynamics.count); missing: none." },
|
|
516
|
-
|
|
527
|
+
livePatterns: { ...SUPPORT, description: "Gray-Scott reaction-diffusion patterns in wet paint (livePatterns); missing: none." },
|
|
528
|
+
iridescence: { ...SUPPORT, description: "Thin-film iridescence (iridescence); missing: none." },
|
|
529
|
+
ferro: { ...SUPPORT, description: "Liquid ferrofluid (ferro); missing: none." }
|
|
517
530
|
},
|
|
518
531
|
required: ["id", "name", "kinds", "tools", "tipShapes", "marks", "surfaces", "exchange", "reservoir", "grain", "light", "motion", "colours", "velocity", "tilt"],
|
|
519
532
|
additionalProperties: false
|
|
@@ -527,16 +540,16 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
|
|
|
527
540
|
brushes: { type: "array", items: { $ref: "brush.schema.json" }, description: "The brushes, each a facet brush (brush.schema.json)." },
|
|
528
541
|
sources: {
|
|
529
542
|
type: "array",
|
|
530
|
-
maxItems:
|
|
543
|
+
maxItems: _chunkHRUK5TFWcjs.MAX_BRUSH_SOURCES,
|
|
531
544
|
description: "The image sources the brushes name (source:<id> in tip.stamps or tip.grain.source), bytes included.",
|
|
532
545
|
items: {
|
|
533
546
|
type: "object",
|
|
534
547
|
description: "An image source: a grey mask, 255 paints (or is a grain peak).",
|
|
535
548
|
properties: {
|
|
536
|
-
id: { type: "string", pattern:
|
|
549
|
+
id: { type: "string", pattern: _chunkHRUK5TFWcjs.BRUSH_ID.source, description: "Source id." },
|
|
537
550
|
name: { type: "string", maxLength: 80, description: "Display name." },
|
|
538
|
-
width: { type: "integer", minimum: 1, maximum:
|
|
539
|
-
height: { type: "integer", minimum: 1, maximum:
|
|
551
|
+
width: { type: "integer", minimum: 1, maximum: _chunkHRUK5TFWcjs.MAX_BRUSH_SOURCE_SIZE, description: "Width in px." },
|
|
552
|
+
height: { type: "integer", minimum: 1, maximum: _chunkHRUK5TFWcjs.MAX_BRUSH_SOURCE_SIZE, description: "Height in px." },
|
|
540
553
|
image: { type: "string", pattern: "^data:image/png;base64,", description: "The mask as a greyscale PNG data: URL." },
|
|
541
554
|
licence: { type: "string", maxLength: 2e3, description: "The licence or terms it came with." },
|
|
542
555
|
origin: { type: "string", maxLength: 200, description: "Where it came from (a file or pack name)." }
|
|
@@ -550,7 +563,7 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
|
|
|
550
563
|
additionalProperties: false
|
|
551
564
|
};
|
|
552
565
|
function migrationInputs() {
|
|
553
|
-
const pick = (id) =>
|
|
566
|
+
const pick = (id) => _chunkHRUK5TFWcjs.brushToJSON.call(void 0, _chunkHRUK5TFWcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
|
|
554
567
|
return [
|
|
555
568
|
{ id: "plain", name: "Plain" },
|
|
556
569
|
pick("pencil-6b"),
|
|
@@ -572,34 +585,34 @@ function migrationInputs() {
|
|
|
572
585
|
function editorSectionFixtures() {
|
|
573
586
|
const ids = ["highlighter", "chalk", "watercolor-wash", "hair-strands", "mixer-brush", "blender", "spray-can"];
|
|
574
587
|
return ids.flatMap(
|
|
575
|
-
(id) => Object.keys(
|
|
576
|
-
const brush =
|
|
577
|
-
return { brush: id, host, sections: brushEditorSections(brush,
|
|
588
|
+
(id) => Object.keys(_chunkHRUK5TFWcjs.BRUSH_HOST_PROFILES).map((host) => {
|
|
589
|
+
const brush = _chunkHRUK5TFWcjs.BRUSH_PRESETS.find((b) => b.id === id);
|
|
590
|
+
return { brush: id, host, sections: brushEditorSections(brush, _chunkHRUK5TFWcjs.BRUSH_HOST_PROFILES[host]) };
|
|
578
591
|
})
|
|
579
592
|
);
|
|
580
593
|
}
|
|
581
594
|
function toolDefinitions() {
|
|
582
|
-
const library =
|
|
583
|
-
const toolsFor = (host) =>
|
|
595
|
+
const library = _chunkHRUK5TFWcjs.createBrushLibrary.call(void 0, );
|
|
596
|
+
const toolsFor = (host) => _chunkJVFGK3DKcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkHRUK5TFWcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
|
|
584
597
|
return {
|
|
585
598
|
tools: toolsFor("paint").map((t) => ({ name: t.name, title: t.title, description: t.description, inputSchema: t.inputSchema, annotations: t.annotations })),
|
|
586
|
-
hosts: Object.fromEntries(Object.keys(
|
|
599
|
+
hosts: Object.fromEntries(Object.keys(_chunkHRUK5TFWcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
|
|
587
600
|
};
|
|
588
601
|
}
|
|
589
602
|
function brushContracts() {
|
|
590
|
-
const presets =
|
|
591
|
-
const resolved =
|
|
592
|
-
const profiles = Object.values(
|
|
593
|
-
const checks =
|
|
603
|
+
const presets = _chunkHRUK5TFWcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
|
|
604
|
+
const resolved = _chunkHRUK5TFWcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkHRUK5TFWcjs.resolveEngine.call(void 0, b), category: _chunkHRUK5TFWcjs.resolveCategory.call(void 0, b), brush: _chunkHRUK5TFWcjs.brushToJSON.call(void 0, _chunkHRUK5TFWcjs.resolveBrush.call(void 0, b)) }));
|
|
605
|
+
const profiles = Object.values(_chunkHRUK5TFWcjs.BRUSH_HOST_PROFILES);
|
|
606
|
+
const checks = _chunkHRUK5TFWcjs.BRUSH_PRESETS.map((b) => ({
|
|
594
607
|
id: b.id,
|
|
595
608
|
hosts: Object.fromEntries(profiles.map((p) => {
|
|
596
|
-
const c =
|
|
609
|
+
const c = _chunkHRUK5TFWcjs.checkBrush.call(void 0, b, p);
|
|
597
610
|
return [p.id, { ok: c.ok, issues: c.issues.map(({ facet, severity }) => ({ facet, severity })) }];
|
|
598
611
|
}))
|
|
599
612
|
}));
|
|
600
|
-
const migrations = migrationInputs().map((input) => ({ input, output:
|
|
613
|
+
const migrations = migrationInputs().map((input) => ({ input, output: _chunkHRUK5TFWcjs.migrateBrushV1.call(void 0, input), resolved: _chunkHRUK5TFWcjs.brushToJSON.call(void 0, _chunkHRUK5TFWcjs.resolveBrush.call(void 0, _chunkHRUK5TFWcjs.migrateBrushV1.call(void 0, input))), engine: _chunkHRUK5TFWcjs.normalizePaintBrush.call(void 0, input).engine }));
|
|
601
614
|
const files = {
|
|
602
|
-
"brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ...
|
|
615
|
+
"brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkHRUK5TFWcjs.BRUSH_JSON_SCHEMA },
|
|
603
616
|
"profile.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "profile.schema.json", ...BRUSH_PROFILE_JSON_SCHEMA },
|
|
604
617
|
"library-file.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "library-file.schema.json", ...BRUSH_LIBRARY_FILE_JSON_SCHEMA },
|
|
605
618
|
"presets.json": presets,
|
|
@@ -613,7 +626,7 @@ function brushContracts() {
|
|
|
613
626
|
files["manifest.json"] = {
|
|
614
627
|
domain: "brushes",
|
|
615
628
|
formatVersion: BRUSH_CONTRACT_FORMAT_VERSION,
|
|
616
|
-
limits: { maxPalette:
|
|
629
|
+
limits: { maxPalette: _chunkHRUK5TFWcjs.MAX_BRUSH_PALETTE },
|
|
617
630
|
counts: { presets: presets.length, profiles: profiles.length, migrations: migrations.length, editorSections: files["editor-sections.json"].length },
|
|
618
631
|
files: Object.keys(files).sort()
|
|
619
632
|
};
|
|
@@ -714,4 +727,4 @@ function brushContracts() {
|
|
|
714
727
|
|
|
715
728
|
|
|
716
729
|
|
|
717
|
-
exports.AbrError =
|
|
730
|
+
exports.AbrError = _chunkJVFGK3DKcjs.AbrError; exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkHRUK5TFWcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_FLIPS = _chunkHRUK5TFWcjs.BRUSH_FLIPS; exports.BRUSH_GRAIN_MODES = _chunkHRUK5TFWcjs.BRUSH_GRAIN_MODES; exports.BRUSH_GRAIN_SOURCE_PATTERN = _chunkHRUK5TFWcjs.BRUSH_GRAIN_SOURCE_PATTERN; exports.BRUSH_HOST_PROFILES = _chunkHRUK5TFWcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkHRUK5TFWcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkHRUK5TFWcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkHRUK5TFWcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkHRUK5TFWcjs.BRUSH_MEDIA; exports.BRUSH_PACK_FORMATS = _chunkJVFGK3DKcjs.BRUSH_PACK_FORMATS; exports.BRUSH_PATCH_PROPERTIES = _chunkJVFGK3DKcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkHRUK5TFWcjs.BRUSH_PRESETS; exports.BRUSH_PREVIEW_DARK_PAPER = _chunkH3EME3S5cjs.BRUSH_PREVIEW_DARK_PAPER; exports.BRUSH_PREVIEW_FALLBACKS = _chunkH3EME3S5cjs.BRUSH_PREVIEW_FALLBACKS; exports.BRUSH_PREVIEW_MIN_CONTRAST = _chunkH3EME3S5cjs.BRUSH_PREVIEW_MIN_CONTRAST; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SOURCE_CHANNELS = _chunkHRUK5TFWcjs.BRUSH_SOURCE_CHANNELS; exports.BRUSH_SOURCE_PROVIDER = _chunkHRUK5TFWcjs.BRUSH_SOURCE_PROVIDER; exports.BRUSH_SURFACES = _chunkHRUK5TFWcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkHRUK5TFWcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkHRUK5TFWcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunkJVFGK3DKcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkHRUK5TFWcjs.BRUSH_WORD; exports.BrushLibraryError = _chunkHRUK5TFWcjs.BrushLibraryError; exports.BrushPackError = _chunkJVFGK3DKcjs.BrushPackError; exports.BrushSourceError = _chunkHRUK5TFWcjs.BrushSourceError; exports.CANVAS_PROFILE = _chunkHRUK5TFWcjs.CANVAS_PROFILE; exports.GHOST_TRIGGERS = _chunkHRUK5TFWcjs.GHOST_TRIGGERS2; exports.IMAGE_PROFILE = _chunkHRUK5TFWcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PACK_BYTES = _chunkJVFGK3DKcjs.MAX_BRUSH_PACK_BYTES; exports.MAX_BRUSH_PALETTE = _chunkHRUK5TFWcjs.MAX_BRUSH_PALETTE; exports.MAX_BRUSH_SOURCES = _chunkHRUK5TFWcjs.MAX_BRUSH_SOURCES; exports.MAX_BRUSH_SOURCE_INPUT_PIXELS = _chunkHRUK5TFWcjs.MAX_BRUSH_SOURCE_INPUT_PIXELS; exports.MAX_BRUSH_SOURCE_SIZE = _chunkHRUK5TFWcjs.MAX_BRUSH_SOURCE_SIZE; exports.MAX_PACK_BRUSHES = _chunkJVFGK3DKcjs.MAX_PACK_BRUSHES; exports.PAINT_PROFILE = _chunkHRUK5TFWcjs.PAINT_PROFILE; exports.TIP_GRAIN_PATTERNS = _chunkHRUK5TFWcjs.TIP_GRAIN_PATTERNS; exports.UNSETTABLE_BRUSH_FACETS = _chunkJVFGK3DKcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkHRUK5TFWcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkHRUK5TFWcjs.WET_BRUSH_TOOLS; exports.addBrushSourceFromFile = addBrushSourceFromFile; exports.brushColourHex = _chunkJBZRVLXVcjs.brushColourHex; exports.brushColourKind = _chunkHRUK5TFWcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.brushPackFormat = _chunkJVFGK3DKcjs.brushPackFormat; exports.brushPreviewColours = _chunkH3EME3S5cjs.brushPreviewColours; exports.brushPreviewStrength = _chunkH3EME3S5cjs.brushPreviewStrength; exports.brushPreviewsOnDark = _chunkH3EME3S5cjs.brushPreviewsOnDark; exports.brushSourceFromMask = _chunkHRUK5TFWcjs.brushSourceFromMask; exports.brushSourceIdFromName = _chunkHRUK5TFWcjs.brushSourceIdFromName; exports.brushSourceIdOf = _chunkHRUK5TFWcjs.brushSourceIdOf; exports.brushSourceIds = _chunkHRUK5TFWcjs.brushSourceIds; exports.brushSourceRef = _chunkHRUK5TFWcjs.brushSourceRef; exports.changedBrushPaths = _chunkJVFGK3DKcjs.changedBrushPaths; exports.checkBrush = _chunkHRUK5TFWcjs.checkBrush; exports.checkBrushEdit = _chunkHRUK5TFWcjs.checkBrushEdit; exports.createBrushLibrary = _chunkHRUK5TFWcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunkJVFGK3DKcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunkJVFGK3DKcjs.createBrushLibraryTools; exports.decodeBrushSource = _chunkHRUK5TFWcjs.decodeBrushSource; exports.degrade = _chunkHRUK5TFWcjs.degrade; exports.imageFileToPngDataUrl = imageFileToPngDataUrl; exports.importBrushFile = _chunkJVFGK3DKcjs.importBrushFile; exports.importBrushPack = _chunkJVFGK3DKcjs.importBrushPack; exports.isBrushLibrary = _chunkHRUK5TFWcjs.isBrushLibrary; exports.isBrushSourceRef = _chunkHRUK5TFWcjs.isBrushSourceRef; exports.listPresets = _chunkHRUK5TFWcjs.listPresets; exports.makeBrushSource = _chunkHRUK5TFWcjs.makeBrushSource; exports.mergeBrushPatch = _chunkJVFGK3DKcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkHRUK5TFWcjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunkHRUK5TFWcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkHRUK5TFWcjs.parseBrushLibrary2; exports.parseBrushLibrarySources = _chunkHRUK5TFWcjs.parseBrushLibrarySources; exports.readAbr = _chunkJVFGK3DKcjs.readAbr; exports.readBrushPack = _chunkJVFGK3DKcjs.readBrushPack; exports.readBrushSource = _chunkHRUK5TFWcjs.readBrushSource; exports.resolveBrush = _chunkHRUK5TFWcjs.resolveBrush; exports.resolveCategory = _chunkHRUK5TFWcjs.resolveCategory; exports.resolveEngine = _chunkHRUK5TFWcjs.resolveEngine; exports.resolveWetMedium = _chunkHRUK5TFWcjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkHRUK5TFWcjs.snapshotBrushLibrary; exports.summarizeBrushSource = _chunkHRUK5TFWcjs.summarizeBrushSource; exports.withBrushSource = withBrushSource; exports.withKeptIssues = _chunkHRUK5TFWcjs.withKeptIssues;
|
package/dist/brushes/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
mergeBrushPatch,
|
|
19
19
|
readAbr,
|
|
20
20
|
readBrushPack
|
|
21
|
-
} from "../chunk-
|
|
21
|
+
} from "../chunk-NJLPW4MM.js";
|
|
22
22
|
import "../chunk-VE6UKYQ2.js";
|
|
23
23
|
import {
|
|
24
24
|
BRUSH_PREVIEW_DARK_PAPER,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
brushPreviewColours,
|
|
28
28
|
brushPreviewStrength,
|
|
29
29
|
brushPreviewsOnDark
|
|
30
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-ROURHJYT.js";
|
|
31
31
|
import {
|
|
32
32
|
BRUSH_FACET_SCHEMAS,
|
|
33
33
|
BRUSH_FIELDS,
|
|
@@ -102,7 +102,7 @@ import {
|
|
|
102
102
|
snapshotBrushLibrary,
|
|
103
103
|
summarizeBrushSource,
|
|
104
104
|
withKeptIssues
|
|
105
|
-
} from "../chunk-
|
|
105
|
+
} from "../chunk-PPDUCZZV.js";
|
|
106
106
|
import {
|
|
107
107
|
STAMP_KINDS
|
|
108
108
|
} from "../chunk-JL6YH5WD.js";
|
|
@@ -112,8 +112,9 @@ import {
|
|
|
112
112
|
import "../chunk-SZTI6EER.js";
|
|
113
113
|
import "../chunk-V2ZCJRDM.js";
|
|
114
114
|
import {
|
|
115
|
+
LIVE_PATTERN_KINDS,
|
|
115
116
|
MAX_BRUSH_SIZE
|
|
116
|
-
} from "../chunk-
|
|
117
|
+
} from "../chunk-LDZOXESA.js";
|
|
117
118
|
import "../chunk-4D6KP5BV.js";
|
|
118
119
|
import {
|
|
119
120
|
BLEND_MODES
|
|
@@ -162,7 +163,8 @@ var ARIA = {
|
|
|
162
163
|
"behaviour.thick.applicator": "Impasto tool",
|
|
163
164
|
"light.pressure": "Light follows pressure",
|
|
164
165
|
"tip.grain.source": "Tip grain",
|
|
165
|
-
"dynamics.angleJitter": "Brush rotation jitter"
|
|
166
|
+
"dynamics.angleJitter": "Brush rotation jitter",
|
|
167
|
+
"livePatterns.pattern": "Live pattern"
|
|
166
168
|
};
|
|
167
169
|
var aria = (path, label) => ARIA[path] ?? `Brush ${label.toLowerCase()}`;
|
|
168
170
|
function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
|
|
@@ -273,7 +275,11 @@ function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
|
|
|
273
275
|
...engineSliders.map((c) => exchangeOk(facetOf(c.path)) ? slider(c) : null),
|
|
274
276
|
engineOk && engineControls?.mixingPath && (engine === "wet" || exchangeFull) && fieldOf("behaviour.mixing") && choice("behaviour.mixing", "Mixing", options(["pigment", "rgb"], { pigment: "Pigment", rgb: "RGB" })),
|
|
275
277
|
engineOk && engineControls?.dirty && exchangeFull && fieldOf("behaviour.exchange.dirty") && toggle("behaviour.exchange.dirty", "Dirty brush"),
|
|
276
|
-
engine === "mixer" && engineOk && full(profile.reservoir) && toggle("behaviour.exchange.reservoir.refill", "Load each stroke")
|
|
278
|
+
engine === "mixer" && engineOk && full(profile.reservoir) && toggle("behaviour.exchange.reservoir.refill", "Load each stroke"),
|
|
279
|
+
engine === "wet" && engineOk && !isTool && full(profile.livePatterns ?? "none") && choice("livePatterns.pattern", "Live pattern", [{ value: "", label: "None" }, ...options(LIVE_PATTERN_KINDS)], ""),
|
|
280
|
+
engine === "wet" && engineOk && !isTool && full(profile.livePatterns ?? "none") && !!brush.livePatterns && withNote({ kind: "slider", path: "livePatterns.scale", label: "Pattern scale", ariaLabel: "Brush pattern scale", min: 0.5, max: 4, step: 0.1, value: brush.livePatterns.scale ?? 1 }),
|
|
281
|
+
engine === "wet" && engineOk && !isTool && full(profile.livePatterns ?? "none") && !!brush.livePatterns && withNote({ kind: "slider", path: "livePatterns.contrast", label: "Pattern contrast", ariaLabel: "Brush pattern contrast", min: 0, max: 2, step: 0.05, value: brush.livePatterns.contrast ?? 1 }),
|
|
282
|
+
engine === "wet" && engineOk && !isTool && full(profile.livePatterns ?? "none") && !!brush.livePatterns && withNote({ kind: "slider", path: "livePatterns.relief", label: "Pattern relief", ariaLabel: "Brush pattern relief", min: 0, max: 1, step: 0.05, value: brush.livePatterns.relief ?? 0 })
|
|
277
283
|
]);
|
|
278
284
|
if (!isTool && full(profile.light) && engineOk && engineControls?.light) {
|
|
279
285
|
add("light", "Light", [
|
|
@@ -338,6 +344,8 @@ function hiddenLabel(issue, b) {
|
|
|
338
344
|
return "several dabs per step";
|
|
339
345
|
case "light":
|
|
340
346
|
return "light";
|
|
347
|
+
case "livePatterns":
|
|
348
|
+
return "live patterns";
|
|
341
349
|
case "fluorescence":
|
|
342
350
|
return "UV-fluorescent ink";
|
|
343
351
|
case "thermochromic":
|
|
@@ -413,6 +421,7 @@ function setBrushEditorValue(brush, path, value) {
|
|
|
413
421
|
delete next.iridescence;
|
|
414
422
|
delete next.ghost;
|
|
415
423
|
delete next.mutation;
|
|
424
|
+
delete next.ferro;
|
|
416
425
|
delete next.colour;
|
|
417
426
|
next.tool = next.tool ?? "eraser";
|
|
418
427
|
if (next.tip.shape === "stamp") next.tip = { shape: "round", ...next.tip.size !== void 0 ? { size: next.tip.size } : {} };
|
|
@@ -427,6 +436,8 @@ function setBrushEditorValue(brush, path, value) {
|
|
|
427
436
|
else delete next.iridescence;
|
|
428
437
|
} else if (path === "tip.grain.source" && (value === void 0 || value === "")) {
|
|
429
438
|
delete next.tip.grain;
|
|
439
|
+
} else if (path === "livePatterns.pattern" && (value === void 0 || value === "")) {
|
|
440
|
+
delete next.livePatterns;
|
|
430
441
|
} else if (path === "tip.shape" && value !== "stamp") {
|
|
431
442
|
next.tip = { ...next.tip, shape: value, stamps: void 0 };
|
|
432
443
|
if (value !== "bristle") delete next.tip.bristle;
|
|
@@ -513,7 +524,9 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
|
|
|
513
524
|
tilt: { ...SUPPORT, description: "Tilt dynamics." },
|
|
514
525
|
tipGrain: { ...SUPPORT, description: "Texture inside the tip (tip.grain); missing: none." },
|
|
515
526
|
dabCount: { ...SUPPORT, description: "Several dabs per spacing step (dynamics.count); missing: none." },
|
|
516
|
-
|
|
527
|
+
livePatterns: { ...SUPPORT, description: "Gray-Scott reaction-diffusion patterns in wet paint (livePatterns); missing: none." },
|
|
528
|
+
iridescence: { ...SUPPORT, description: "Thin-film iridescence (iridescence); missing: none." },
|
|
529
|
+
ferro: { ...SUPPORT, description: "Liquid ferrofluid (ferro); missing: none." }
|
|
517
530
|
},
|
|
518
531
|
required: ["id", "name", "kinds", "tools", "tipShapes", "marks", "surfaces", "exchange", "reservoir", "grain", "light", "motion", "colours", "velocity", "tilt"],
|
|
519
532
|
additionalProperties: false
|
package/dist/brushes/patch.d.cts
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
* means the same everywhere.
|
|
6
6
|
*/
|
|
7
7
|
import type { JsonSchema } from '../tools/schema.cjs';
|
|
8
|
-
import type { Brush } from './types.cjs';
|
|
9
|
-
/** A brush's facets, any of them, as a patch takes them (the tip's `shape` may be left out). */
|
|
8
|
+
import type { Brush, BrushFerro } from './types.cjs';
|
|
9
|
+
/** A brush's facets, any of them, as a patch takes them (the tip's `shape` may be left out, and `ferro` accepts a `0..1` amount shorthand). */
|
|
10
10
|
export type BrushPatch = {
|
|
11
|
-
[K in Exclude<keyof Brush, 'id'>]?: K extends 'tip' ? Partial<Brush['tip']> : Brush[K];
|
|
11
|
+
[K in Exclude<keyof Brush, 'id'>]?: K extends 'tip' ? Partial<Brush['tip']> : K extends 'ferro' ? number | BrushFerro : Brush[K];
|
|
12
12
|
};
|
|
13
13
|
/** The schema of every facet except `id` and `name`, as tool arguments (a patch may leave out `tip.shape`). */
|
|
14
14
|
export declare const BRUSH_PATCH_PROPERTIES: Readonly<Record<string, JsonSchema>>;
|
|
15
15
|
/** The facets a patch can remove (`unset`), back to the engine's defaults. */
|
|
16
|
-
export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "motion", "colour"];
|
|
16
|
+
export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "ferro", "motion", "livePatterns", "colour"];
|
|
17
17
|
export type UnsettableBrushFacet = (typeof UNSETTABLE_BRUSH_FACETS)[number];
|
|
18
18
|
/** The `unset` argument of tools that take a patch. */
|
|
19
19
|
export declare const BRUSH_UNSET_PROPERTY: JsonSchema;
|
package/dist/brushes/patch.d.ts
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
* means the same everywhere.
|
|
6
6
|
*/
|
|
7
7
|
import type { JsonSchema } from '../tools/schema.js';
|
|
8
|
-
import type { Brush } from './types.js';
|
|
9
|
-
/** A brush's facets, any of them, as a patch takes them (the tip's `shape` may be left out). */
|
|
8
|
+
import type { Brush, BrushFerro } from './types.js';
|
|
9
|
+
/** A brush's facets, any of them, as a patch takes them (the tip's `shape` may be left out, and `ferro` accepts a `0..1` amount shorthand). */
|
|
10
10
|
export type BrushPatch = {
|
|
11
|
-
[K in Exclude<keyof Brush, 'id'>]?: K extends 'tip' ? Partial<Brush['tip']> : Brush[K];
|
|
11
|
+
[K in Exclude<keyof Brush, 'id'>]?: K extends 'tip' ? Partial<Brush['tip']> : K extends 'ferro' ? number | BrushFerro : Brush[K];
|
|
12
12
|
};
|
|
13
13
|
/** The schema of every facet except `id` and `name`, as tool arguments (a patch may leave out `tip.shape`). */
|
|
14
14
|
export declare const BRUSH_PATCH_PROPERTIES: Readonly<Record<string, JsonSchema>>;
|
|
15
15
|
/** The facets a patch can remove (`unset`), back to the engine's defaults. */
|
|
16
|
-
export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "motion", "colour"];
|
|
16
|
+
export declare const UNSETTABLE_BRUSH_FACETS: readonly ["description", "tags", "medium", "variety", "marks", "dynamics", "behaviour", "light", "fluorescence", "thermochromic", "iridescence", "ghost", "mutation", "ferro", "motion", "livePatterns", "colour"];
|
|
17
17
|
export type UnsettableBrushFacet = (typeof UNSETTABLE_BRUSH_FACETS)[number];
|
|
18
18
|
/** The `unset` argument of tools that take a patch. */
|
|
19
19
|
export declare const BRUSH_UNSET_PROPERTY: JsonSchema;
|
|
@@ -39,8 +39,12 @@ export interface BrushHostProfile {
|
|
|
39
39
|
tipGrain?: BrushSupport;
|
|
40
40
|
/** Several dabs per spacing step (`dynamics.count` above 1); missing: `none`. */
|
|
41
41
|
dabCount?: BrushSupport;
|
|
42
|
+
/** Gray-Scott reaction-diffusion patterns in wet paint (`livePatterns`); missing: `none`. */
|
|
43
|
+
livePatterns?: BrushSupport;
|
|
42
44
|
/** Structural colour (`iridescence`); missing: `none`. */
|
|
43
45
|
iridescence?: BrushSupport;
|
|
46
|
+
/** Liquid ferrofluid (`ferro`); missing: `none`. */
|
|
47
|
+
ferro?: BrushSupport;
|
|
44
48
|
}
|
|
45
49
|
export interface BrushIssue {
|
|
46
50
|
/** The facet path the issue is about, e.g. `tip.shape`, `light`, `behaviour.exchange.reservoir`. */
|