@pixerate/editor 0.281.0 → 0.282.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 +59 -59
- package/dist/animation-editor/index.js +3 -3
- package/dist/brushes/index.cjs +76 -71
- package/dist/brushes/index.js +13 -8
- package/dist/brushes/schema.d.cts +1 -0
- package/dist/brushes/schema.d.ts +1 -0
- package/dist/brushes/types.d.cts +29 -3
- package/dist/brushes/types.d.ts +29 -3
- package/dist/{brushstrokeRender-EIK3625T.js → brushstrokeRender-4MA5CBW3.js} +3 -3
- package/dist/{brushstrokeRender-7HOMKZNO.cjs → brushstrokeRender-JVKVKWDA.cjs} +15 -15
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-NJDEKU5D.js → chunk-2YGYYVSG.js} +1 -1
- package/dist/{chunk-JVFGK3DK.cjs → chunk-3JUKN3RM.cjs} +76 -53
- package/dist/{chunk-HN57I7KT.js → chunk-CG3FBNXE.js} +1 -1
- package/dist/{chunk-WFSYZO5Z.cjs → chunk-DFZ4I7EZ.cjs} +1 -1
- package/dist/{chunk-LZE2QZCT.js → chunk-IHMMHZGP.js} +1 -1
- package/dist/{chunk-K4ANWBF7.cjs → chunk-IJQ2YH2M.cjs} +35 -35
- package/dist/{chunk-HRUK5TFW.cjs → chunk-IUKPQCYQ.cjs} +164 -71
- package/dist/{chunk-WCC4NXWY.cjs → chunk-JD63B33V.cjs} +86 -86
- package/dist/{chunk-NJLPW4MM.js → chunk-KV7QHPKL.js} +27 -4
- package/dist/{chunk-H3EME3S5.cjs → chunk-MRIAR5DY.cjs} +2 -2
- package/dist/{chunk-ROURHJYT.js → chunk-NEDS6DSC.js} +1 -1
- package/dist/{chunk-FKO3CY2C.js → chunk-ULPXJ3NB.js} +1 -1
- package/dist/{chunk-WZYRYYXN.cjs → chunk-UOM5S4W5.cjs} +12 -12
- package/dist/{chunk-YOM76H2V.js → chunk-VEX6YVNG.js} +1 -1
- package/dist/{chunk-MNHP3AQT.cjs → chunk-WEXWDBUF.cjs} +23 -23
- package/dist/{chunk-PPDUCZZV.js → chunk-YRGTQLDN.js} +122 -29
- package/dist/image-editor/index.cjs +788 -788
- package/dist/image-editor/index.js +4 -4
- package/dist/paint-editor/antimatter.d.cts +154 -0
- package/dist/paint-editor/antimatter.d.ts +154 -0
- package/dist/paint-editor/brush-controls.d.cts +1 -0
- package/dist/paint-editor/brush-controls.d.ts +1 -0
- package/dist/paint-editor/brush-model.d.cts +9 -5
- package/dist/paint-editor/brush-model.d.ts +9 -5
- package/dist/paint-editor/controller.d.cts +23 -0
- package/dist/paint-editor/controller.d.ts +23 -0
- package/dist/paint-editor/index.cjs +1931 -891
- package/dist/paint-editor/index.d.cts +1 -0
- package/dist/paint-editor/index.d.ts +1 -0
- package/dist/paint-editor/index.js +1098 -58
- package/dist/paint-editor/mark-settings.d.cts +30 -0
- package/dist/paint-editor/mark-settings.d.ts +30 -0
- package/dist/paint-editor/stroke.d.cts +16 -0
- package/dist/paint-editor/stroke.d.ts +16 -0
- package/dist/paint-editor/strokes.d.cts +2 -0
- package/dist/paint-editor/strokes.d.ts +2 -0
- package/dist/paint-editor/ui.d.cts +4 -2
- package/dist/paint-editor/ui.d.ts +4 -2
- package/dist/vector/index.cjs +999 -999
- package/dist/vector/index.js +4 -4
- package/package.json +1 -1
- package/skills/pixerate-brushes/SKILL.md +1 -1
- package/skills/pixerate-paint-editor/SKILL.md +8 -2
- package/skills/pixerate-paint-editor/references/antimatter.md +49 -0
- package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
package/dist/brushes/index.cjs
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
var
|
|
21
|
+
var _chunk3JUKN3RMcjs = require('../chunk-3JUKN3RM.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 _chunkMRIAR5DYcjs = require('../chunk-MRIAR5DY.cjs');
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
@@ -102,7 +102,8 @@ var _chunkH3EME3S5cjs = require('../chunk-H3EME3S5.cjs');
|
|
|
102
102
|
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
|
|
106
|
+
var _chunkIUKPQCYQcjs = require('../chunk-IUKPQCYQ.cjs');
|
|
106
107
|
|
|
107
108
|
|
|
108
109
|
var _chunkRDFHWAHLcjs = require('../chunk-RDFHWAHL.cjs');
|
|
@@ -138,7 +139,7 @@ var options = (values, labels = {}) => values.map((value) => ({ value, label: _n
|
|
|
138
139
|
var MEDIUM_LABELS = { paint: "Paint", ink: "Ink", dry: "Dry media", spray: "Spray" };
|
|
139
140
|
var TOOL_LABELS = { eraser: "Eraser", blender: "Blender", smudge: "Smudge", water: "Add water", dryer: "Dry", blow: "Blow", blot: "Blot", "wet-blend": "Wet blend", "wet-drag": "Wet smudge" };
|
|
140
141
|
var SHAPE_LABELS = { round: "Round", flat: "Flat", chisel: "Chisel", bristle: "Bristle", stamp: "Stamp" };
|
|
141
|
-
var MARKS_LABELS = { continuous: "Continuous", particles: "Particles", objects: "Stickers" };
|
|
142
|
+
var MARKS_LABELS = { continuous: "Continuous", particles: "Particles", objects: "Stickers", antimatter: "Antimatter" };
|
|
142
143
|
var SURFACE_LABELS = { dry: "Dry", wet: "Wet (flows)", thick: "Thick (impasto)" };
|
|
143
144
|
var ROTATION_LABELS = { fixed: "Fixed", stroke: "Follow stroke", barrel: "Pen barrel" };
|
|
144
145
|
var PHYSICS_LABELS = { string: "Strings", spring: "Springs", orbit: "Orbits", flow: "Flow", elastic: "Elastic", fuzzy: "Fuzzy" };
|
|
@@ -159,6 +160,7 @@ var ARIA = {
|
|
|
159
160
|
"marks.ribbonPairs": "Ribbon pairs",
|
|
160
161
|
"marks.stampOrder": "Dot texture order",
|
|
161
162
|
"marks.stampRotation": "Dot rotation",
|
|
163
|
+
"marks.invertMode": "Inversion mode",
|
|
162
164
|
"behaviour.wet.medium": "Wet medium",
|
|
163
165
|
"behaviour.thick.applicator": "Impasto tool",
|
|
164
166
|
"light.pressure": "Light follows pressure",
|
|
@@ -167,20 +169,20 @@ var ARIA = {
|
|
|
167
169
|
"livePatterns.pattern": "Live pattern"
|
|
168
170
|
};
|
|
169
171
|
var aria = (path, label) => _nullishCoalesce(ARIA[path], () => ( `Brush ${label.toLowerCase()}`));
|
|
170
|
-
function brushEditorSections(brush, profile =
|
|
171
|
-
const resolved =
|
|
172
|
-
const engine =
|
|
173
|
-
const fieldOf = (facet) =>
|
|
174
|
-
const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(
|
|
172
|
+
function brushEditorSections(brush, profile = _chunkIUKPQCYQcjs.PAINT_PROFILE, context = {}) {
|
|
173
|
+
const resolved = _chunkIUKPQCYQcjs.resolveBrush.call(void 0, brush);
|
|
174
|
+
const engine = _chunkIUKPQCYQcjs.resolveEngine.call(void 0, brush);
|
|
175
|
+
const fieldOf = (facet) => _chunkIUKPQCYQcjs.BRUSH_FIELDS.find((f) => f.facet === facet && f.engines.includes(engine));
|
|
176
|
+
const facetOf = (enginePath) => _optionalChain([(_nullishCoalesce(_chunkIUKPQCYQcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath && f.engines.includes(engine)), () => ( _chunkIUKPQCYQcjs.BRUSH_FIELDS.find((f) => f.engine === enginePath)))), 'optionalAccess', _ => _.facet]);
|
|
175
177
|
const value = (path) => {
|
|
176
|
-
const own =
|
|
178
|
+
const own = _chunkIUKPQCYQcjs.getPath.call(void 0, brush, path);
|
|
177
179
|
if (own !== void 0) return own;
|
|
178
180
|
const field = fieldOf(path);
|
|
179
181
|
if (!field) return void 0;
|
|
180
|
-
const v =
|
|
182
|
+
const v = _chunkIUKPQCYQcjs.getPath.call(void 0, resolved, field.engine);
|
|
181
183
|
return field.map ? field.map.toFacet(v) : v;
|
|
182
184
|
};
|
|
183
|
-
const issues =
|
|
185
|
+
const issues = _chunkIUKPQCYQcjs.checkBrush.call(void 0, brush, profile).issues;
|
|
184
186
|
const warned = new Map(issues.filter((i) => i.severity === "warning").map((i) => [i.facet, i.reason]));
|
|
185
187
|
const refused = new Set(issues.filter((i) => i.severity === "error").map((i) => i.facet));
|
|
186
188
|
const full = (s) => s === "full";
|
|
@@ -205,30 +207,30 @@ function brushEditorSections(brush, profile = _chunkHRUK5TFWcjs.PAINT_PROFILE, c
|
|
|
205
207
|
};
|
|
206
208
|
const isTool = brush.kind === "tool";
|
|
207
209
|
const shape = brush.tip.shape;
|
|
208
|
-
const sourceOptions = (_nullishCoalesce(context.sources, () => ( []))).map((x) => ({ value:
|
|
210
|
+
const sourceOptions = (_nullishCoalesce(context.sources, () => ( []))).map((x) => ({ value: _chunkIUKPQCYQcjs.brushSourceRef.call(void 0, x.id), label: x.name }));
|
|
209
211
|
const marks = _nullishCoalesce(_optionalChain([brush, 'access', _7 => _7.marks, 'optionalAccess', _8 => _8.kind]), () => ( "continuous"));
|
|
210
212
|
const exchangeFull = full(_optionalChain([brush, 'access', _9 => _9.behaviour, 'optionalAccess', _10 => _10.exchange, 'optionalAccess', _11 => _11.reservoir]) ? profile.reservoir : profile.exchange);
|
|
211
213
|
add("medium", "Medium", [
|
|
212
214
|
profile.kinds.length > 1 && profile.kinds.includes(brush.kind) && choice("kind", "Kind", options(profile.kinds, { mark: "Lays a material", tool: "Works on paint" })),
|
|
213
|
-
!isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(
|
|
215
|
+
!isTool && choice("medium", "Medium", [{ value: "", label: "Any" }, ...options(_chunkIUKPQCYQcjs.BRUSH_MEDIA, MEDIUM_LABELS)], ""),
|
|
214
216
|
!isTool && withNote({ kind: "text", path: "variety", label: "Variety", ariaLabel: "Brush variety", value: _nullishCoalesce(brush.variety, () => ( "")), placeholder: "pencil, oil, highlighter\u2026" }),
|
|
215
217
|
isTool && !!brush.tool && profile.tools.includes(brush.tool) && choice("tool", "Tool", options(profile.tools, TOOL_LABELS))
|
|
216
218
|
]);
|
|
217
|
-
const engineControls =
|
|
218
|
-
const tipSliders =
|
|
219
|
+
const engineControls = _chunk3JUKN3RMcjs.brushEngineControls.call(void 0, resolved);
|
|
220
|
+
const tipSliders = _chunk3JUKN3RMcjs.BRUSH_SLIDERS.filter((c) => c.path.startsWith("tip.") && c.path !== "tip.smoothing");
|
|
219
221
|
add("shape", "Shape", [
|
|
220
222
|
!refused.has("tip.shape") && choice("tip.shape", "Tip", options(profile.tipShapes.filter((s) => !isTool || s !== "stamp"), SHAPE_LABELS)),
|
|
221
223
|
...tipSliders.map((c) => slider(c)),
|
|
222
224
|
engine === "dab" && choice("tip.blend", "Blend", _chunk2VX55NFMcjs.BLEND_MODES.map((m) => ({ value: m.id, label: m.label })), "normal"),
|
|
223
225
|
...shape === "bristle" && engineOk && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("bristle.")).map((c) => slider(c)) : [],
|
|
224
|
-
shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ?
|
|
226
|
+
shape === "stamp" && engineOk && withNote({ kind: "stamps", path: "tip.stamps", label: "Stamps", ariaLabel: "Brush stamps", value: [..._nullishCoalesce(value("tip.stamps"), () => ( []))], max: marks === "particles" ? _chunkIUKPQCYQcjs.MAX_DOT_TEXTURES : _chunkIUKPQCYQcjs.MAX_STICKER_STAMPS, options: marks === "objects" ? STAMP_OPTIONS : [...STAMP_OPTIONS, ...sourceOptions] })
|
|
225
227
|
]);
|
|
226
228
|
const dabs = DAB_ENGINES.has(engine) && engineOk && shape !== "bristle" && marks !== "particles" && marks !== "objects";
|
|
227
229
|
const grain = brush.tip.grain;
|
|
228
230
|
if (dabs && full(_nullishCoalesce(profile.tipGrain, () => ( "none")))) {
|
|
229
231
|
add("grain", "Tip grain", [
|
|
230
|
-
choice("tip.grain.source", "Texture", [{ value: "", label: "None" }, ...options(
|
|
231
|
-
!!grain && choice("tip.grain.mode", "Grain moves", options(
|
|
232
|
+
choice("tip.grain.source", "Texture", [{ value: "", label: "None" }, ...options(_chunkIUKPQCYQcjs.TIP_GRAIN_PATTERNS), ...sourceOptions], ""),
|
|
233
|
+
!!grain && choice("tip.grain.mode", "Grain moves", options(_chunkIUKPQCYQcjs.BRUSH_GRAIN_MODES, GRAIN_MODE_LABELS), "texturised"),
|
|
232
234
|
!!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)) }),
|
|
233
235
|
!!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)) }),
|
|
234
236
|
!!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)) }),
|
|
@@ -238,40 +240,43 @@ function brushEditorSections(brush, profile = _chunkHRUK5TFWcjs.PAINT_PROFILE, c
|
|
|
238
240
|
if (!isTool && profile.marks.length > 1 && engineOk) {
|
|
239
241
|
const particles = marks === "particles" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("particle.") && c.path !== "particle.waveSpeed") : [];
|
|
240
242
|
const objects = marks === "objects" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("sticker.")) : [];
|
|
243
|
+
const antimatter = marks === "antimatter" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("antimatter.")) : [];
|
|
241
244
|
const render = value("marks.render");
|
|
242
245
|
add("marks", "Marks", [
|
|
243
246
|
choice("marks.kind", "Laid as", options(profile.marks, MARKS_LABELS), "continuous"),
|
|
244
|
-
marks === "particles" && choice("marks.physics", "Particles", options(
|
|
245
|
-
marks === "particles" && choice("marks.render", "Drawn as", options(
|
|
246
|
-
marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(
|
|
247
|
-
marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(
|
|
248
|
-
marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(
|
|
247
|
+
marks === "particles" && choice("marks.physics", "Particles", options(_chunkIUKPQCYQcjs.PARTICLE_KINDS, PHYSICS_LABELS)),
|
|
248
|
+
marks === "particles" && choice("marks.render", "Drawn as", options(_chunkIUKPQCYQcjs.PARTICLE_RENDERS, RENDER_LABELS)),
|
|
249
|
+
marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(_chunkIUKPQCYQcjs.RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
|
|
250
|
+
marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(_chunkIUKPQCYQcjs.DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
|
|
251
|
+
marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(_chunkIUKPQCYQcjs.DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
|
|
252
|
+
marks === "antimatter" && choice("marks.invertMode", "Inversion mode", options(_chunkIUKPQCYQcjs.INVERT_MODES, { rgb: "RGB", oklab: "OKLab" }), "rgb"),
|
|
249
253
|
...particles.map((c) => slider(c)),
|
|
250
|
-
...objects.map((c) => slider(c))
|
|
254
|
+
...objects.map((c) => slider(c)),
|
|
255
|
+
...antimatter.map((c) => slider(c))
|
|
251
256
|
]);
|
|
252
257
|
}
|
|
253
|
-
const feel =
|
|
258
|
+
const feel = _chunk3JUKN3RMcjs.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)));
|
|
254
259
|
const stampDabs = dabs && shape === "stamp";
|
|
255
260
|
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))) });
|
|
256
261
|
add("feel", "Feel", [
|
|
257
262
|
...feel.map((c) => slider(c)),
|
|
258
263
|
toggle("dynamics.pressureSize", "Pressure \u2192 size"),
|
|
259
264
|
toggle("dynamics.pressureOpacity", "Pressure \u2192 opacity"),
|
|
260
|
-
choice("dynamics.rotation", "Rotation", options(
|
|
265
|
+
choice("dynamics.rotation", "Rotation", options(_chunkIUKPQCYQcjs.BRUSH_ROTATIONS, ROTATION_LABELS)),
|
|
261
266
|
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)) }),
|
|
262
267
|
stampDabs && jitter("dynamics.scatter", "Scatter", 4),
|
|
263
268
|
stampDabs && jitter("dynamics.angleJitter", "Rotation jitter"),
|
|
264
269
|
stampDabs && jitter("dynamics.sizeJitter", "Size jitter"),
|
|
265
|
-
stampDabs && choice("dynamics.flip", "Flip", options(
|
|
270
|
+
stampDabs && choice("dynamics.flip", "Flip", options(_chunkIUKPQCYQcjs.BRUSH_FLIPS, FLIP_LABELS), "none")
|
|
266
271
|
]);
|
|
267
272
|
const surfaces = profile.surfaces;
|
|
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");
|
|
273
|
+
const engineSliders = (engineOk ? _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _14 => _14.sliders]), () => ( [])) : []).filter((c) => !/^(bristle|particle|sticker|antimatter|iridescence)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
|
|
269
274
|
const exchangeOk = (path) => !_optionalChain([path, 'optionalAccess', _15 => _15.startsWith, 'call', _16 => _16("behaviour.exchange")]) || (path.startsWith("behaviour.exchange.reservoir") ? full(profile.reservoir) : exchangeFull);
|
|
270
275
|
add("behaviour", _nullishCoalesce(_optionalChain([engineControls, 'optionalAccess', _17 => _17.title]), () => ( "Behaviour")), [
|
|
271
276
|
!isTool && surfaces.length > 1 && !refused.has("behaviour.surface") && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
|
|
272
277
|
full(profile.grain) && slider({ path: "grain", label: "Grain", min: 0, max: 1, step: 0.01 }, "behaviour.grain"),
|
|
273
|
-
engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(
|
|
274
|
-
engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(
|
|
278
|
+
engine === "wet" && engineOk && !isTool && choice("behaviour.wet.medium", "Medium", options(_chunkIUKPQCYQcjs.WET_MEDIA, WET_MEDIUM_LABELS), "watercolor"),
|
|
279
|
+
engine === "impasto" && engineOk && choice("behaviour.thick.applicator", "Tool", options(_chunkIUKPQCYQcjs.IMPASTO_TOOLS, APPLICATOR_LABELS), "brush"),
|
|
275
280
|
...engineSliders.map((c) => exchangeOk(facetOf(c.path)) ? slider(c) : null),
|
|
276
281
|
engineOk && _optionalChain([engineControls, 'optionalAccess', _18 => _18.mixingPath]) && (engine === "wet" || exchangeFull) && fieldOf("behaviour.mixing") && choice("behaviour.mixing", "Mixing", options(["pigment", "rgb"], { pigment: "Pigment", rgb: "RGB" })),
|
|
277
282
|
engineOk && _optionalChain([engineControls, 'optionalAccess', _19 => _19.dirty]) && exchangeFull && fieldOf("behaviour.exchange.dirty") && toggle("behaviour.exchange.dirty", "Dirty brush"),
|
|
@@ -292,7 +297,7 @@ function brushEditorSections(brush, profile = _chunkHRUK5TFWcjs.PAINT_PROFILE, c
|
|
|
292
297
|
toggle("fluorescence.invisible", "Invisible in daylight"),
|
|
293
298
|
withNote({ kind: "colour", path: "thermochromic.hotColor", label: "Hot colour", ariaLabel: "Brush thermochromic hot colour", value: _nullishCoalesce(_optionalChain([brush, 'access', _26 => _26.thermochromic, 'optionalAccess', _27 => _27.hotColor]), () => ( null)), dark: null, gradient: false }),
|
|
294
299
|
withNote({ kind: "slider", path: "thermochromic.threshold", label: "Heat threshold", ariaLabel: "Brush thermochromic threshold", min: 0.05, max: 0.95, step: 0.01, value: _nullishCoalesce(_optionalChain([brush, 'access', _28 => _28.thermochromic, 'optionalAccess', _29 => _29.threshold]), () => ( 0.5)) }),
|
|
295
|
-
full(_nullishCoalesce(profile.iridescence, () => ( "none"))) && marks !== "objects" && withNote({ kind: "toggle", path: "iridescence", label: "Thin-film iridescence", ariaLabel: "Brush thin-film iridescence", value: Boolean(brush.iridescence) }),
|
|
300
|
+
full(_nullishCoalesce(profile.iridescence, () => ( "none"))) && marks !== "objects" && marks !== "antimatter" && withNote({ kind: "toggle", path: "iridescence", label: "Thin-film iridescence", ariaLabel: "Brush thin-film iridescence", value: Boolean(brush.iridescence) }),
|
|
296
301
|
...brush.iridescence && full(_nullishCoalesce(profile.iridescence, () => ( "none"))) ? [
|
|
297
302
|
slider({ path: "iridescence.thickness", label: "Film (nm)", min: 100, max: 1e3, step: 5 }),
|
|
298
303
|
slider({ path: "iridescence.pressureToThickness", label: "Pressure \u2192 film", min: 0, max: 1, step: 0.01 }),
|
|
@@ -313,14 +318,14 @@ function brushEditorSections(brush, profile = _chunkHRUK5TFWcjs.PAINT_PROFILE, c
|
|
|
313
318
|
label: "Palette",
|
|
314
319
|
ariaLabel: "Brush palette",
|
|
315
320
|
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)] : []),
|
|
316
|
-
max:
|
|
321
|
+
max: _chunkIUKPQCYQcjs.MAX_BRUSH_PALETTE
|
|
317
322
|
}),
|
|
318
323
|
toggle("colour.own", "Always its own colour")
|
|
319
324
|
]);
|
|
320
325
|
}
|
|
321
326
|
return sections;
|
|
322
327
|
}
|
|
323
|
-
var MARKS_WORDS = { particles: "particle marks", objects: "sticker marks", continuous: "continuous marks" };
|
|
328
|
+
var MARKS_WORDS = { particles: "particle marks", objects: "sticker marks", continuous: "continuous marks", antimatter: "antimatter marks" };
|
|
324
329
|
function hiddenLabel(issue, b) {
|
|
325
330
|
switch (issue.facet) {
|
|
326
331
|
case "kind":
|
|
@@ -363,15 +368,15 @@ function hiddenLabel(issue, b) {
|
|
|
363
368
|
case "dynamics.tilt":
|
|
364
369
|
return "tilt dynamics";
|
|
365
370
|
case "colour.default":
|
|
366
|
-
return `a ${
|
|
371
|
+
return `a ${_chunkIUKPQCYQcjs.brushColourKind.call(void 0, b.colour.default)} default colour`;
|
|
367
372
|
default:
|
|
368
373
|
return null;
|
|
369
374
|
}
|
|
370
375
|
}
|
|
371
376
|
var sentence = (words) => words.length < 2 ? _nullishCoalesce(words[0], () => ( "")) : `${words.slice(0, -1).join(", ")} and ${words.at(-1)}`;
|
|
372
|
-
function brushEditorScope(brush, profile =
|
|
377
|
+
function brushEditorScope(brush, profile = _chunkIUKPQCYQcjs.PAINT_PROFILE) {
|
|
373
378
|
const hidden = [];
|
|
374
|
-
for (const issue of
|
|
379
|
+
for (const issue of _chunkIUKPQCYQcjs.checkBrush.call(void 0, brush, profile).issues) {
|
|
375
380
|
const label = hiddenLabel(issue, brush);
|
|
376
381
|
if (label && !hidden.some((h) => h.label === label)) hidden.push({ facet: issue.facet, label });
|
|
377
382
|
}
|
|
@@ -384,17 +389,17 @@ function newBrushFor(profile, from, name = "New brush") {
|
|
|
384
389
|
const id = brushIdFromName(name);
|
|
385
390
|
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] } };
|
|
386
391
|
if (from) {
|
|
387
|
-
const stripped =
|
|
392
|
+
const stripped = _chunkIUKPQCYQcjs.degrade.call(void 0, from, profile, { ignored: true });
|
|
388
393
|
if (!stripped.issues.length) return { ...stripped.brush, id, name };
|
|
389
394
|
}
|
|
390
395
|
return base;
|
|
391
396
|
}
|
|
392
397
|
async function saveBrushEdit(library, options2) {
|
|
393
398
|
const { original, profile } = options2;
|
|
394
|
-
const check =
|
|
399
|
+
const check = _chunkIUKPQCYQcjs.checkBrushEdit.call(void 0, original, options2.brush, profile);
|
|
395
400
|
if (!check.ok) {
|
|
396
401
|
const errors = check.issues.filter((i) => i.severity === "error").map((i) => `${i.facet}: ${i.reason} ${i.fix}`);
|
|
397
|
-
throw new (0,
|
|
402
|
+
throw new (0, _chunkIUKPQCYQcjs.BrushLibraryError)("invalid", `${profile.name} can't use this brush: ${errors.join(" ")} Nothing was saved.`);
|
|
398
403
|
}
|
|
399
404
|
const inPlace = !!original && options2.name === void 0 && !library.isBuiltin(original.id) && original.id === options2.brush.id && !!await library.get(original.id);
|
|
400
405
|
let brush = options2.brush;
|
|
@@ -443,13 +448,13 @@ function setBrushEditorValue(brush, path, value) {
|
|
|
443
448
|
if (value !== "bristle") delete next.tip.bristle;
|
|
444
449
|
} else if (value === void 0 || value === "") {
|
|
445
450
|
const keys = path.split(".");
|
|
446
|
-
const parent =
|
|
451
|
+
const parent = _chunkIUKPQCYQcjs.getPath.call(void 0, next, keys.slice(0, -1).join("."));
|
|
447
452
|
if (keys.length === 1) delete next[keys[0]];
|
|
448
453
|
else if (parent) delete parent[keys[keys.length - 1]];
|
|
449
|
-
} else
|
|
454
|
+
} else _chunkIUKPQCYQcjs.setPath.call(void 0, next, path, value);
|
|
450
455
|
const problems = [];
|
|
451
456
|
try {
|
|
452
|
-
return { brush:
|
|
457
|
+
return { brush: _chunkIUKPQCYQcjs.normalizeBrushSpec.call(void 0, JSON.parse(JSON.stringify(next)), problems), problems };
|
|
453
458
|
} catch (e) {
|
|
454
459
|
return { brush, problems: [e.message] };
|
|
455
460
|
}
|
|
@@ -465,7 +470,7 @@ function brushLibraryGroups(entries, filter = {}) {
|
|
|
465
470
|
const text = words([b.id, b.name, _nullishCoalesce(b.variety, () => ( "")), _nullishCoalesce(b.medium, () => ( "")), _nullishCoalesce(b.tool, () => ( "")), ..._nullishCoalesce(b.tags, () => ( []))].join(" "));
|
|
466
471
|
if (!wanted.every((w) => text.some((t) => t.startsWith(w)))) continue;
|
|
467
472
|
}
|
|
468
|
-
if (filter.profile && !
|
|
473
|
+
if (filter.profile && !_chunkIUKPQCYQcjs.checkBrush.call(void 0, b, filter.profile).ok) continue;
|
|
469
474
|
const id = b.kind === "tool" ? "tools" : _nullishCoalesce(b.medium, () => ( "other"));
|
|
470
475
|
let g = groups.get(id);
|
|
471
476
|
if (!g) groups.set(id, g = { id, title: id === "tools" ? "Tools" : id === "other" ? "Other" : MEDIUM_LABELS[id], varieties: [] });
|
|
@@ -481,7 +486,7 @@ async function imageFileToPngDataUrl(file) {
|
|
|
481
486
|
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
482
487
|
if (_chunkW5M3J7PVcjs.isPng.call(void 0, bytes)) return `data:image/png;base64,${_chunkW5M3J7PVcjs.bytesToBase64.call(void 0, bytes)}`;
|
|
483
488
|
const g = globalThis;
|
|
484
|
-
if (!g.createImageBitmap || !g.OffscreenCanvas) throw new (0,
|
|
489
|
+
if (!g.createImageBitmap || !g.OffscreenCanvas) throw new (0, _chunkIUKPQCYQcjs.BrushSourceError)("Only PNG images can be read here; convert the image to PNG.");
|
|
485
490
|
const bitmap = await g.createImageBitmap(file);
|
|
486
491
|
const canvas = new g.OffscreenCanvas(bitmap.width, bitmap.height);
|
|
487
492
|
canvas.getContext("2d").drawImage(bitmap, 0, 0);
|
|
@@ -491,7 +496,7 @@ async function imageFileToPngDataUrl(file) {
|
|
|
491
496
|
async function addBrushSourceFromFile(library, file, options2 = {}) {
|
|
492
497
|
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";
|
|
493
498
|
const result = await library.addSource({ name, image: await imageFileToPngDataUrl(file), origin: file.name, ...options2.channel ? { channel: options2.channel } : {} });
|
|
494
|
-
return { ...result, ref:
|
|
499
|
+
return { ...result, ref: _chunkIUKPQCYQcjs.brushSourceRef.call(void 0, result.source.id) };
|
|
495
500
|
}
|
|
496
501
|
function withBrushSource(brush, ref, as) {
|
|
497
502
|
if (as === "grain") return setBrushEditorValue(brush, "tip.grain.source", ref);
|
|
@@ -509,11 +514,11 @@ var BRUSH_PROFILE_JSON_SCHEMA = {
|
|
|
509
514
|
properties: {
|
|
510
515
|
id: { type: "string", description: "paint, image, canvas, vector\u2026" },
|
|
511
516
|
name: { type: "string", description: "Display name, used in messages." },
|
|
512
|
-
kinds: { type: "array", items: { type: "string", enum: [...
|
|
513
|
-
tools: { type: "array", items: { type: "string", enum: [...
|
|
514
|
-
tipShapes: { type: "array", items: { type: "string", enum: [...
|
|
515
|
-
marks: { type: "array", items: { type: "string", enum: [...
|
|
516
|
-
surfaces: { type: "array", items: { type: "string", enum: [...
|
|
517
|
+
kinds: { type: "array", items: { type: "string", enum: [..._chunkIUKPQCYQcjs.BRUSH_KINDS] }, description: "Brush kinds it has." },
|
|
518
|
+
tools: { type: "array", items: { type: "string", enum: [..._chunkIUKPQCYQcjs.BRUSH_TOOLS] }, description: "Tools it has (kind tool)." },
|
|
519
|
+
tipShapes: { type: "array", items: { type: "string", enum: [..._chunkIUKPQCYQcjs.BRUSH_TIP_SHAPES] }, description: "Tip shapes it renders." },
|
|
520
|
+
marks: { type: "array", items: { type: "string", enum: [..._chunkIUKPQCYQcjs.BRUSH_MARKS_KINDS] }, description: "Marks kinds it renders." },
|
|
521
|
+
surfaces: { type: "array", items: { type: "string", enum: [..._chunkIUKPQCYQcjs.BRUSH_SURFACES] }, description: "Surfaces it renders." },
|
|
517
522
|
exchange: { ...SUPPORT, description: "Picking paint up and mixing it in." },
|
|
518
523
|
reservoir: { ...SUPPORT, description: "The Mixer Brush reservoir." },
|
|
519
524
|
grain: { ...SUPPORT, description: "Paper grain response." },
|
|
@@ -540,16 +545,16 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
|
|
|
540
545
|
brushes: { type: "array", items: { $ref: "brush.schema.json" }, description: "The brushes, each a facet brush (brush.schema.json)." },
|
|
541
546
|
sources: {
|
|
542
547
|
type: "array",
|
|
543
|
-
maxItems:
|
|
548
|
+
maxItems: _chunkIUKPQCYQcjs.MAX_BRUSH_SOURCES,
|
|
544
549
|
description: "The image sources the brushes name (source:<id> in tip.stamps or tip.grain.source), bytes included.",
|
|
545
550
|
items: {
|
|
546
551
|
type: "object",
|
|
547
552
|
description: "An image source: a grey mask, 255 paints (or is a grain peak).",
|
|
548
553
|
properties: {
|
|
549
|
-
id: { type: "string", pattern:
|
|
554
|
+
id: { type: "string", pattern: _chunkIUKPQCYQcjs.BRUSH_ID.source, description: "Source id." },
|
|
550
555
|
name: { type: "string", maxLength: 80, description: "Display name." },
|
|
551
|
-
width: { type: "integer", minimum: 1, maximum:
|
|
552
|
-
height: { type: "integer", minimum: 1, maximum:
|
|
556
|
+
width: { type: "integer", minimum: 1, maximum: _chunkIUKPQCYQcjs.MAX_BRUSH_SOURCE_SIZE, description: "Width in px." },
|
|
557
|
+
height: { type: "integer", minimum: 1, maximum: _chunkIUKPQCYQcjs.MAX_BRUSH_SOURCE_SIZE, description: "Height in px." },
|
|
553
558
|
image: { type: "string", pattern: "^data:image/png;base64,", description: "The mask as a greyscale PNG data: URL." },
|
|
554
559
|
licence: { type: "string", maxLength: 2e3, description: "The licence or terms it came with." },
|
|
555
560
|
origin: { type: "string", maxLength: 200, description: "Where it came from (a file or pack name)." }
|
|
@@ -563,7 +568,7 @@ var BRUSH_LIBRARY_FILE_JSON_SCHEMA = {
|
|
|
563
568
|
additionalProperties: false
|
|
564
569
|
};
|
|
565
570
|
function migrationInputs() {
|
|
566
|
-
const pick = (id) =>
|
|
571
|
+
const pick = (id) => _chunkIUKPQCYQcjs.brushToJSON.call(void 0, _chunkIUKPQCYQcjs.BUILTIN_BRUSHES.find((b) => b.id === id));
|
|
567
572
|
return [
|
|
568
573
|
{ id: "plain", name: "Plain" },
|
|
569
574
|
pick("pencil-6b"),
|
|
@@ -585,34 +590,34 @@ function migrationInputs() {
|
|
|
585
590
|
function editorSectionFixtures() {
|
|
586
591
|
const ids = ["highlighter", "chalk", "watercolor-wash", "hair-strands", "mixer-brush", "blender", "spray-can"];
|
|
587
592
|
return ids.flatMap(
|
|
588
|
-
(id) => Object.keys(
|
|
589
|
-
const brush =
|
|
590
|
-
return { brush: id, host, sections: brushEditorSections(brush,
|
|
593
|
+
(id) => Object.keys(_chunkIUKPQCYQcjs.BRUSH_HOST_PROFILES).map((host) => {
|
|
594
|
+
const brush = _chunkIUKPQCYQcjs.BRUSH_PRESETS.find((b) => b.id === id);
|
|
595
|
+
return { brush: id, host, sections: brushEditorSections(brush, _chunkIUKPQCYQcjs.BRUSH_HOST_PROFILES[host]) };
|
|
591
596
|
})
|
|
592
597
|
);
|
|
593
598
|
}
|
|
594
599
|
function toolDefinitions() {
|
|
595
|
-
const library =
|
|
596
|
-
const toolsFor = (host) =>
|
|
600
|
+
const library = _chunkIUKPQCYQcjs.createBrushLibrary.call(void 0, );
|
|
601
|
+
const toolsFor = (host) => _chunk3JUKN3RMcjs.createBrushLibraryTools.call(void 0, library, { profile: _chunkIUKPQCYQcjs.BRUSH_HOST_PROFILES[host], renderPreview: () => ({ data: "", mimeType: "image/png" }) });
|
|
597
602
|
return {
|
|
598
603
|
tools: toolsFor("paint").map((t) => ({ name: t.name, title: t.title, description: t.description, inputSchema: t.inputSchema, annotations: t.annotations })),
|
|
599
|
-
hosts: Object.fromEntries(Object.keys(
|
|
604
|
+
hosts: Object.fromEntries(Object.keys(_chunkIUKPQCYQcjs.BRUSH_HOST_PROFILES).map((host) => [host, toolsFor(host).map((t) => t.name)]))
|
|
600
605
|
};
|
|
601
606
|
}
|
|
602
607
|
function brushContracts() {
|
|
603
|
-
const presets =
|
|
604
|
-
const resolved =
|
|
605
|
-
const profiles = Object.values(
|
|
606
|
-
const checks =
|
|
608
|
+
const presets = _chunkIUKPQCYQcjs.BRUSH_PRESETS.map((b) => JSON.parse(JSON.stringify(b)));
|
|
609
|
+
const resolved = _chunkIUKPQCYQcjs.BRUSH_PRESETS.map((b) => ({ id: b.id, engine: _chunkIUKPQCYQcjs.resolveEngine.call(void 0, b), category: _chunkIUKPQCYQcjs.resolveCategory.call(void 0, b), brush: _chunkIUKPQCYQcjs.brushToJSON.call(void 0, _chunkIUKPQCYQcjs.resolveBrush.call(void 0, b)) }));
|
|
610
|
+
const profiles = Object.values(_chunkIUKPQCYQcjs.BRUSH_HOST_PROFILES);
|
|
611
|
+
const checks = _chunkIUKPQCYQcjs.BRUSH_PRESETS.map((b) => ({
|
|
607
612
|
id: b.id,
|
|
608
613
|
hosts: Object.fromEntries(profiles.map((p) => {
|
|
609
|
-
const c =
|
|
614
|
+
const c = _chunkIUKPQCYQcjs.checkBrush.call(void 0, b, p);
|
|
610
615
|
return [p.id, { ok: c.ok, issues: c.issues.map(({ facet, severity }) => ({ facet, severity })) }];
|
|
611
616
|
}))
|
|
612
617
|
}));
|
|
613
|
-
const migrations = migrationInputs().map((input) => ({ input, output:
|
|
618
|
+
const migrations = migrationInputs().map((input) => ({ input, output: _chunkIUKPQCYQcjs.migrateBrushV1.call(void 0, input), resolved: _chunkIUKPQCYQcjs.brushToJSON.call(void 0, _chunkIUKPQCYQcjs.resolveBrush.call(void 0, _chunkIUKPQCYQcjs.migrateBrushV1.call(void 0, input))), engine: _chunkIUKPQCYQcjs.normalizePaintBrush.call(void 0, input).engine }));
|
|
614
619
|
const files = {
|
|
615
|
-
"brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ...
|
|
620
|
+
"brush.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "brush.schema.json", ..._chunkIUKPQCYQcjs.BRUSH_JSON_SCHEMA },
|
|
616
621
|
"profile.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "profile.schema.json", ...BRUSH_PROFILE_JSON_SCHEMA },
|
|
617
622
|
"library-file.schema.json": { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "library-file.schema.json", ...BRUSH_LIBRARY_FILE_JSON_SCHEMA },
|
|
618
623
|
"presets.json": presets,
|
|
@@ -626,7 +631,7 @@ function brushContracts() {
|
|
|
626
631
|
files["manifest.json"] = {
|
|
627
632
|
domain: "brushes",
|
|
628
633
|
formatVersion: BRUSH_CONTRACT_FORMAT_VERSION,
|
|
629
|
-
limits: { maxPalette:
|
|
634
|
+
limits: { maxPalette: _chunkIUKPQCYQcjs.MAX_BRUSH_PALETTE },
|
|
630
635
|
counts: { presets: presets.length, profiles: profiles.length, migrations: migrations.length, editorSections: files["editor-sections.json"].length },
|
|
631
636
|
files: Object.keys(files).sort()
|
|
632
637
|
};
|
|
@@ -727,4 +732,4 @@ function brushContracts() {
|
|
|
727
732
|
|
|
728
733
|
|
|
729
734
|
|
|
730
|
-
exports.AbrError =
|
|
735
|
+
exports.AbrError = _chunk3JUKN3RMcjs.AbrError; exports.BRUSH_CONTRACT_FORMAT_VERSION = BRUSH_CONTRACT_FORMAT_VERSION; exports.BRUSH_FACET_SCHEMAS = _chunkIUKPQCYQcjs.BRUSH_FACET_SCHEMAS; exports.BRUSH_FLIPS = _chunkIUKPQCYQcjs.BRUSH_FLIPS; exports.BRUSH_GRAIN_MODES = _chunkIUKPQCYQcjs.BRUSH_GRAIN_MODES; exports.BRUSH_GRAIN_SOURCE_PATTERN = _chunkIUKPQCYQcjs.BRUSH_GRAIN_SOURCE_PATTERN; exports.BRUSH_HOST_PROFILES = _chunkIUKPQCYQcjs.BRUSH_HOST_PROFILES; exports.BRUSH_JSON_SCHEMA = _chunkIUKPQCYQcjs.BRUSH_JSON_SCHEMA; exports.BRUSH_KINDS = _chunkIUKPQCYQcjs.BRUSH_KINDS; exports.BRUSH_LIBRARY_FILE_JSON_SCHEMA = BRUSH_LIBRARY_FILE_JSON_SCHEMA; exports.BRUSH_MARKS_KINDS = _chunkIUKPQCYQcjs.BRUSH_MARKS_KINDS; exports.BRUSH_MEDIA = _chunkIUKPQCYQcjs.BRUSH_MEDIA; exports.BRUSH_PACK_FORMATS = _chunk3JUKN3RMcjs.BRUSH_PACK_FORMATS; exports.BRUSH_PATCH_PROPERTIES = _chunk3JUKN3RMcjs.BRUSH_PATCH_PROPERTIES; exports.BRUSH_PRESETS = _chunkIUKPQCYQcjs.BRUSH_PRESETS; exports.BRUSH_PREVIEW_DARK_PAPER = _chunkMRIAR5DYcjs.BRUSH_PREVIEW_DARK_PAPER; exports.BRUSH_PREVIEW_FALLBACKS = _chunkMRIAR5DYcjs.BRUSH_PREVIEW_FALLBACKS; exports.BRUSH_PREVIEW_MIN_CONTRAST = _chunkMRIAR5DYcjs.BRUSH_PREVIEW_MIN_CONTRAST; exports.BRUSH_PROFILE_JSON_SCHEMA = BRUSH_PROFILE_JSON_SCHEMA; exports.BRUSH_SOURCE_CHANNELS = _chunkIUKPQCYQcjs.BRUSH_SOURCE_CHANNELS; exports.BRUSH_SOURCE_PROVIDER = _chunkIUKPQCYQcjs.BRUSH_SOURCE_PROVIDER; exports.BRUSH_SURFACES = _chunkIUKPQCYQcjs.BRUSH_SURFACES; exports.BRUSH_TIP_SHAPES = _chunkIUKPQCYQcjs.BRUSH_TIP_SHAPES; exports.BRUSH_TOOLS = _chunkIUKPQCYQcjs.BRUSH_TOOLS; exports.BRUSH_UNSET_PROPERTY = _chunk3JUKN3RMcjs.BRUSH_UNSET_PROPERTY; exports.BRUSH_WORD = _chunkIUKPQCYQcjs.BRUSH_WORD; exports.BrushLibraryError = _chunkIUKPQCYQcjs.BrushLibraryError; exports.BrushPackError = _chunk3JUKN3RMcjs.BrushPackError; exports.BrushSourceError = _chunkIUKPQCYQcjs.BrushSourceError; exports.CANVAS_PROFILE = _chunkIUKPQCYQcjs.CANVAS_PROFILE; exports.GHOST_TRIGGERS = _chunkIUKPQCYQcjs.GHOST_TRIGGERS2; exports.IMAGE_PROFILE = _chunkIUKPQCYQcjs.IMAGE_PROFILE; exports.MAX_BRUSH_PACK_BYTES = _chunk3JUKN3RMcjs.MAX_BRUSH_PACK_BYTES; exports.MAX_BRUSH_PALETTE = _chunkIUKPQCYQcjs.MAX_BRUSH_PALETTE; exports.MAX_BRUSH_SOURCES = _chunkIUKPQCYQcjs.MAX_BRUSH_SOURCES; exports.MAX_BRUSH_SOURCE_INPUT_PIXELS = _chunkIUKPQCYQcjs.MAX_BRUSH_SOURCE_INPUT_PIXELS; exports.MAX_BRUSH_SOURCE_SIZE = _chunkIUKPQCYQcjs.MAX_BRUSH_SOURCE_SIZE; exports.MAX_PACK_BRUSHES = _chunk3JUKN3RMcjs.MAX_PACK_BRUSHES; exports.PAINT_PROFILE = _chunkIUKPQCYQcjs.PAINT_PROFILE; exports.TIP_GRAIN_PATTERNS = _chunkIUKPQCYQcjs.TIP_GRAIN_PATTERNS; exports.UNSETTABLE_BRUSH_FACETS = _chunk3JUKN3RMcjs.UNSETTABLE_BRUSH_FACETS; exports.VECTOR_PROFILE = _chunkIUKPQCYQcjs.VECTOR_PROFILE; exports.WET_BRUSH_TOOLS = _chunkIUKPQCYQcjs.WET_BRUSH_TOOLS; exports.addBrushSourceFromFile = addBrushSourceFromFile; exports.brushColourHex = _chunkJBZRVLXVcjs.brushColourHex; exports.brushColourKind = _chunkIUKPQCYQcjs.brushColourKind; exports.brushContracts = brushContracts; exports.brushEditorScope = brushEditorScope; exports.brushEditorSections = brushEditorSections; exports.brushIdFromName = brushIdFromName; exports.brushLibraryGroups = brushLibraryGroups; exports.brushPackFormat = _chunk3JUKN3RMcjs.brushPackFormat; exports.brushPreviewColours = _chunkMRIAR5DYcjs.brushPreviewColours; exports.brushPreviewStrength = _chunkMRIAR5DYcjs.brushPreviewStrength; exports.brushPreviewsOnDark = _chunkMRIAR5DYcjs.brushPreviewsOnDark; exports.brushSourceFromMask = _chunkIUKPQCYQcjs.brushSourceFromMask; exports.brushSourceIdFromName = _chunkIUKPQCYQcjs.brushSourceIdFromName; exports.brushSourceIdOf = _chunkIUKPQCYQcjs.brushSourceIdOf; exports.brushSourceIds = _chunkIUKPQCYQcjs.brushSourceIds; exports.brushSourceRef = _chunkIUKPQCYQcjs.brushSourceRef; exports.changedBrushPaths = _chunk3JUKN3RMcjs.changedBrushPaths; exports.checkBrush = _chunkIUKPQCYQcjs.checkBrush; exports.checkBrushEdit = _chunkIUKPQCYQcjs.checkBrushEdit; exports.createBrushLibrary = _chunkIUKPQCYQcjs.createBrushLibrary; exports.createBrushLibraryToolProvider = _chunk3JUKN3RMcjs.createBrushLibraryToolProvider; exports.createBrushLibraryTools = _chunk3JUKN3RMcjs.createBrushLibraryTools; exports.decodeBrushSource = _chunkIUKPQCYQcjs.decodeBrushSource; exports.degrade = _chunkIUKPQCYQcjs.degrade; exports.imageFileToPngDataUrl = imageFileToPngDataUrl; exports.importBrushFile = _chunk3JUKN3RMcjs.importBrushFile; exports.importBrushPack = _chunk3JUKN3RMcjs.importBrushPack; exports.isBrushLibrary = _chunkIUKPQCYQcjs.isBrushLibrary; exports.isBrushSourceRef = _chunkIUKPQCYQcjs.isBrushSourceRef; exports.listPresets = _chunkIUKPQCYQcjs.listPresets; exports.makeBrushSource = _chunkIUKPQCYQcjs.makeBrushSource; exports.mergeBrushPatch = _chunk3JUKN3RMcjs.mergeBrushPatch; exports.migrateBrushV1 = _chunkIUKPQCYQcjs.migrateBrushV1; exports.newBrushFor = newBrushFor; exports.normalizeBrushSpec = _chunkIUKPQCYQcjs.normalizeBrushSpec; exports.parseBrushLibrary = _chunkIUKPQCYQcjs.parseBrushLibrary2; exports.parseBrushLibrarySources = _chunkIUKPQCYQcjs.parseBrushLibrarySources; exports.readAbr = _chunk3JUKN3RMcjs.readAbr; exports.readBrushPack = _chunk3JUKN3RMcjs.readBrushPack; exports.readBrushSource = _chunkIUKPQCYQcjs.readBrushSource; exports.resolveBrush = _chunkIUKPQCYQcjs.resolveBrush; exports.resolveCategory = _chunkIUKPQCYQcjs.resolveCategory; exports.resolveEngine = _chunkIUKPQCYQcjs.resolveEngine; exports.resolveWetMedium = _chunkIUKPQCYQcjs.resolveWetMedium; exports.saveBrushEdit = saveBrushEdit; exports.setBrushEditorValue = setBrushEditorValue; exports.snapshotBrushLibrary = _chunkIUKPQCYQcjs.snapshotBrushLibrary; exports.summarizeBrushSource = _chunkIUKPQCYQcjs.summarizeBrushSource; exports.withBrushSource = withBrushSource; exports.withKeptIssues = _chunkIUKPQCYQcjs.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-KV7QHPKL.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-NEDS6DSC.js";
|
|
31
31
|
import {
|
|
32
32
|
BRUSH_FACET_SCHEMAS,
|
|
33
33
|
BRUSH_FIELDS,
|
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
GHOST_TRIGGERS2 as GHOST_TRIGGERS,
|
|
58
58
|
IMAGE_PROFILE,
|
|
59
59
|
IMPASTO_TOOLS,
|
|
60
|
+
INVERT_MODES,
|
|
60
61
|
MAX_BRUSH_PALETTE,
|
|
61
62
|
MAX_BRUSH_SOURCES,
|
|
62
63
|
MAX_BRUSH_SOURCE_INPUT_PIXELS,
|
|
@@ -102,7 +103,7 @@ import {
|
|
|
102
103
|
snapshotBrushLibrary,
|
|
103
104
|
summarizeBrushSource,
|
|
104
105
|
withKeptIssues
|
|
105
|
-
} from "../chunk-
|
|
106
|
+
} from "../chunk-YRGTQLDN.js";
|
|
106
107
|
import {
|
|
107
108
|
STAMP_KINDS
|
|
108
109
|
} from "../chunk-JL6YH5WD.js";
|
|
@@ -138,7 +139,7 @@ var options = (values, labels = {}) => values.map((value) => ({ value, label: la
|
|
|
138
139
|
var MEDIUM_LABELS = { paint: "Paint", ink: "Ink", dry: "Dry media", spray: "Spray" };
|
|
139
140
|
var TOOL_LABELS = { eraser: "Eraser", blender: "Blender", smudge: "Smudge", water: "Add water", dryer: "Dry", blow: "Blow", blot: "Blot", "wet-blend": "Wet blend", "wet-drag": "Wet smudge" };
|
|
140
141
|
var SHAPE_LABELS = { round: "Round", flat: "Flat", chisel: "Chisel", bristle: "Bristle", stamp: "Stamp" };
|
|
141
|
-
var MARKS_LABELS = { continuous: "Continuous", particles: "Particles", objects: "Stickers" };
|
|
142
|
+
var MARKS_LABELS = { continuous: "Continuous", particles: "Particles", objects: "Stickers", antimatter: "Antimatter" };
|
|
142
143
|
var SURFACE_LABELS = { dry: "Dry", wet: "Wet (flows)", thick: "Thick (impasto)" };
|
|
143
144
|
var ROTATION_LABELS = { fixed: "Fixed", stroke: "Follow stroke", barrel: "Pen barrel" };
|
|
144
145
|
var PHYSICS_LABELS = { string: "Strings", spring: "Springs", orbit: "Orbits", flow: "Flow", elastic: "Elastic", fuzzy: "Fuzzy" };
|
|
@@ -159,6 +160,7 @@ var ARIA = {
|
|
|
159
160
|
"marks.ribbonPairs": "Ribbon pairs",
|
|
160
161
|
"marks.stampOrder": "Dot texture order",
|
|
161
162
|
"marks.stampRotation": "Dot rotation",
|
|
163
|
+
"marks.invertMode": "Inversion mode",
|
|
162
164
|
"behaviour.wet.medium": "Wet medium",
|
|
163
165
|
"behaviour.thick.applicator": "Impasto tool",
|
|
164
166
|
"light.pressure": "Light follows pressure",
|
|
@@ -238,6 +240,7 @@ function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
|
|
|
238
240
|
if (!isTool && profile.marks.length > 1 && engineOk) {
|
|
239
241
|
const particles = marks === "particles" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("particle.") && c.path !== "particle.waveSpeed") : [];
|
|
240
242
|
const objects = marks === "objects" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("sticker.")) : [];
|
|
243
|
+
const antimatter = marks === "antimatter" && engineControls ? engineControls.sliders.filter((c) => c.path.startsWith("antimatter.")) : [];
|
|
241
244
|
const render = value("marks.render");
|
|
242
245
|
add("marks", "Marks", [
|
|
243
246
|
choice("marks.kind", "Laid as", options(profile.marks, MARKS_LABELS), "continuous"),
|
|
@@ -246,8 +249,10 @@ function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
|
|
|
246
249
|
marks === "particles" && render === "ribbon" && choice("marks.ribbonPairs", "Ribbon joins", options(RIBBON_PAIRS, { adjacent: "Neighbours", "first-last": "Outermost" })),
|
|
247
250
|
marks === "particles" && shape === "stamp" && choice("marks.stampOrder", "Texture order", options(DOT_TEXTURE_ORDERS, { sequence: "In turn", random: "Random" })),
|
|
248
251
|
marks === "particles" && shape === "stamp" && choice("marks.stampRotation", "Texture turn", options(DOT_ROTATIONS, { follow: "Follow motion", random: "Random", fixed: "Tip angle" })),
|
|
252
|
+
marks === "antimatter" && choice("marks.invertMode", "Inversion mode", options(INVERT_MODES, { rgb: "RGB", oklab: "OKLab" }), "rgb"),
|
|
249
253
|
...particles.map((c) => slider(c)),
|
|
250
|
-
...objects.map((c) => slider(c))
|
|
254
|
+
...objects.map((c) => slider(c)),
|
|
255
|
+
...antimatter.map((c) => slider(c))
|
|
251
256
|
]);
|
|
252
257
|
}
|
|
253
258
|
const feel = 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)));
|
|
@@ -265,7 +270,7 @@ function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
|
|
|
265
270
|
stampDabs && choice("dynamics.flip", "Flip", options(BRUSH_FLIPS, FLIP_LABELS), "none")
|
|
266
271
|
]);
|
|
267
272
|
const surfaces = profile.surfaces;
|
|
268
|
-
const engineSliders = (engineOk ? engineControls?.sliders ?? [] : []).filter((c) => !/^(bristle|particle|sticker|iridescence)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
|
|
273
|
+
const engineSliders = (engineOk ? engineControls?.sliders ?? [] : []).filter((c) => !/^(bristle|particle|sticker|antimatter|iridescence)\./.test(c.path) && c.path !== "light.amount" && c.path !== "impasto.rim" && c.path !== "impasto.clarity");
|
|
269
274
|
const exchangeOk = (path) => !path?.startsWith("behaviour.exchange") || (path.startsWith("behaviour.exchange.reservoir") ? full(profile.reservoir) : exchangeFull);
|
|
270
275
|
add("behaviour", engineControls?.title ?? "Behaviour", [
|
|
271
276
|
!isTool && surfaces.length > 1 && !refused.has("behaviour.surface") && choice("behaviour.surface", "Surface", options(surfaces, SURFACE_LABELS), "dry"),
|
|
@@ -292,7 +297,7 @@ function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
|
|
|
292
297
|
toggle("fluorescence.invisible", "Invisible in daylight"),
|
|
293
298
|
withNote({ kind: "colour", path: "thermochromic.hotColor", label: "Hot colour", ariaLabel: "Brush thermochromic hot colour", value: brush.thermochromic?.hotColor ?? null, dark: null, gradient: false }),
|
|
294
299
|
withNote({ kind: "slider", path: "thermochromic.threshold", label: "Heat threshold", ariaLabel: "Brush thermochromic threshold", min: 0.05, max: 0.95, step: 0.01, value: brush.thermochromic?.threshold ?? 0.5 }),
|
|
295
|
-
full(profile.iridescence ?? "none") && marks !== "objects" && withNote({ kind: "toggle", path: "iridescence", label: "Thin-film iridescence", ariaLabel: "Brush thin-film iridescence", value: Boolean(brush.iridescence) }),
|
|
300
|
+
full(profile.iridescence ?? "none") && marks !== "objects" && marks !== "antimatter" && withNote({ kind: "toggle", path: "iridescence", label: "Thin-film iridescence", ariaLabel: "Brush thin-film iridescence", value: Boolean(brush.iridescence) }),
|
|
296
301
|
...brush.iridescence && full(profile.iridescence ?? "none") ? [
|
|
297
302
|
slider({ path: "iridescence.thickness", label: "Film (nm)", min: 100, max: 1e3, step: 5 }),
|
|
298
303
|
slider({ path: "iridescence.pressureToThickness", label: "Pressure \u2192 film", min: 0, max: 1, step: 0.01 }),
|
|
@@ -320,7 +325,7 @@ function brushEditorSections(brush, profile = PAINT_PROFILE, context = {}) {
|
|
|
320
325
|
}
|
|
321
326
|
return sections;
|
|
322
327
|
}
|
|
323
|
-
var MARKS_WORDS = { particles: "particle marks", objects: "sticker marks", continuous: "continuous marks" };
|
|
328
|
+
var MARKS_WORDS = { particles: "particle marks", objects: "sticker marks", continuous: "continuous marks", antimatter: "antimatter marks" };
|
|
324
329
|
function hiddenLabel(issue, b) {
|
|
325
330
|
switch (issue.facet) {
|
|
326
331
|
case "kind":
|
package/dist/brushes/schema.d.ts
CHANGED
package/dist/brushes/types.d.cts
CHANGED
|
@@ -16,7 +16,7 @@ import type { MixingModel } from '../paint/exchange.cjs';
|
|
|
16
16
|
import type { BlendMode } from '../raster/blend.cjs';
|
|
17
17
|
import type { BrushRotation, ImpastoTool, LivePatternKind, PaintBrush, WetMediumKind } from '../paint-editor/brushes.cjs';
|
|
18
18
|
import type { PaintEffectPaint } from '../paint-editor/effect-paint.cjs';
|
|
19
|
-
import type { DotRotation, DotTextureOrder, ParticleKind, ParticleRender, RibbonPairs } from '../paint-editor/mark-settings.cjs';
|
|
19
|
+
import type { DotRotation, DotTextureOrder, InvertMode, ParticleKind, ParticleRender, RibbonPairs } from '../paint-editor/mark-settings.cjs';
|
|
20
20
|
import type { StickerRef } from '../stickers/types.cjs';
|
|
21
21
|
/** `mark`: lays a material; `tool`: works on paint already down (erases, blends, smudges, wets…). */
|
|
22
22
|
export type BrushKind = 'mark' | 'tool';
|
|
@@ -35,7 +35,7 @@ export declare const BRUSH_TOOLS: readonly BrushTool[];
|
|
|
35
35
|
export type BrushTipShape = 'round' | 'flat' | 'chisel' | 'bristle' | 'stamp';
|
|
36
36
|
export declare const BRUSH_TIP_SHAPES: readonly BrushTipShape[];
|
|
37
37
|
/** How the tip is laid along the path. */
|
|
38
|
-
export type BrushMarksKind = 'continuous' | 'scatter' | 'particles' | 'objects';
|
|
38
|
+
export type BrushMarksKind = 'continuous' | 'scatter' | 'particles' | 'objects' | 'antimatter';
|
|
39
39
|
export declare const BRUSH_MARKS_KINDS: readonly BrushMarksKind[];
|
|
40
40
|
/** What the material does on the surface: stays where it lands (`dry`), flows and dries (`wet`) or stands up in relief (`thick`). */
|
|
41
41
|
export type BrushSurface = 'dry' | 'wet' | 'thick';
|
|
@@ -178,7 +178,33 @@ export interface BrushObjectMarks {
|
|
|
178
178
|
/** Random colour change, hue and lightness (default 0.2). */
|
|
179
179
|
colourJitter?: number;
|
|
180
180
|
}
|
|
181
|
-
|
|
181
|
+
/** Animated blasts that invert, scorch and destroy paint across every visible layer where the tip touches paint. */
|
|
182
|
+
export interface BrushAntimatterMarks {
|
|
183
|
+
kind: 'antimatter';
|
|
184
|
+
/** Blast size, in tip radii, 1..6 (default 2.5). */
|
|
185
|
+
blastRadius?: number;
|
|
186
|
+
/** Stroke travel between blasts, in tip diameters, 0.5..8 (default 2). */
|
|
187
|
+
blastSpacing?: number;
|
|
188
|
+
/** Paint needed under the tip to fire, 0..1 (default 0.1). */
|
|
189
|
+
threshold?: number;
|
|
190
|
+
/** Strength of the colour inversion in the blast core, 0..1 (default 1). */
|
|
191
|
+
invert?: number;
|
|
192
|
+
/** Colour inversion mode: `rgb` (default) or `oklab` (flips lightness and hue so mid-grey changes too). */
|
|
193
|
+
invertMode?: InvertMode;
|
|
194
|
+
/** Strength of the soot ring, 0..1 (default 0.6). */
|
|
195
|
+
scorch?: number;
|
|
196
|
+
/** Paint destroyed at the centre — alpha removed, 0..1 (default 0.25). */
|
|
197
|
+
annihilate?: number;
|
|
198
|
+
/** How many sparks fly out from each blast, 0..1 (default 0.5). */
|
|
199
|
+
sparks?: number;
|
|
200
|
+
/** How far sparks fly, in tip diameters, 0.5..8 (default 3). */
|
|
201
|
+
sparkReach?: number;
|
|
202
|
+
/** Depth of the dent on layers with relief, 0..1 (default 0.5). */
|
|
203
|
+
crater?: number;
|
|
204
|
+
/** Seconds a blast plays on screen, 0..2 (default 0.7; 0 shows the result at once). */
|
|
205
|
+
duration?: number;
|
|
206
|
+
}
|
|
207
|
+
export type BrushMarks = BrushContinuousMarks | BrushScatterMarks | BrushParticleMarks | BrushObjectMarks | BrushAntimatterMarks;
|
|
182
208
|
/** Pen feel. Every amount is 0 (off) .. 1 unless noted. */
|
|
183
209
|
export interface BrushDynamics {
|
|
184
210
|
/** Pressure scales the size (default true). */
|