@pixerate/editor 0.275.1 → 0.276.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 +81 -70
- package/dist/brushes/index.js +17 -6
- package/dist/brushes/patch.d.cts +1 -1
- package/dist/brushes/patch.d.ts +1 -1
- package/dist/brushes/profiles.d.cts +2 -0
- package/dist/brushes/profiles.d.ts +2 -0
- package/dist/brushes/schema.d.cts +1 -0
- package/dist/brushes/schema.d.ts +1 -0
- package/dist/brushes/types.d.cts +22 -1
- package/dist/brushes/types.d.ts +22 -1
- package/dist/{brushstrokeRender-WGY4DZHF.js → brushstrokeRender-FK3ASUUJ.js} +5 -5
- package/dist/{brushstrokeRender-2RQL46WB.cjs → brushstrokeRender-I6MYFCOU.cjs} +21 -21
- package/dist/canvas/index.cjs +13 -13
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-Y2ISSVPH.js → chunk-4EM5NGCL.js} +167 -9
- package/dist/{chunk-Y354ETAE.cjs → chunk-5HR5CSLC.cjs} +49 -49
- package/dist/{chunk-LMG57L5A.js → chunk-CTHWXW5M.js} +121 -8
- package/dist/{chunk-43XJC3PP.js → chunk-CVBTJVRN.js} +1 -1
- package/dist/{chunk-RJGW3RQS.js → chunk-GHYJAMMS.js} +1 -1
- package/dist/{chunk-NIBFKXMD.cjs → chunk-IFWLZZCW.cjs} +619 -2
- package/dist/{chunk-G5TCMKX5.js → chunk-IJ6NSWKM.js} +2 -2
- package/dist/{chunk-C6VB7CPY.cjs → chunk-ISCAJBPQ.cjs} +1 -1
- package/dist/{chunk-W6JDUXP3.js → chunk-J23JOHPR.js} +1 -1
- package/dist/{chunk-IEEY5RJV.js → chunk-JNMNM3SL.js} +1 -1
- package/dist/{chunk-HVO6XCI4.js → chunk-JPB65KQ6.js} +1 -1
- package/dist/{chunk-ACTHSQOI.js → chunk-LDZOXESA.js} +618 -1
- package/dist/{chunk-DHC4E2DU.cjs → chunk-MITQGHN3.cjs} +121 -8
- package/dist/{chunk-STLTOISW.cjs → chunk-NPPMKMCU.cjs} +17 -17
- package/dist/{chunk-75SYKUOT.js → chunk-OS6OG7DN.js} +1 -1
- package/dist/{chunk-OLZXXAER.cjs → chunk-OY24XRYF.cjs} +408 -250
- package/dist/{chunk-6QNDGMK7.cjs → chunk-Q33V5PEF.cjs} +123 -42
- package/dist/{chunk-JDXWLCXF.cjs → chunk-QNNZA3V5.cjs} +2 -2
- package/dist/{chunk-T6KNJVBP.cjs → chunk-U26LUXCJ.cjs} +35 -35
- package/dist/{chunk-62MFUHSI.cjs → chunk-UQXULAMQ.cjs} +16 -16
- package/dist/{chunk-RAPNRK4R.cjs → chunk-X7XBEX3O.cjs} +88 -88
- package/dist/{chunk-MSWLJI4G.js → chunk-XMSH66VU.js} +2 -2
- package/dist/{chunk-ZM7IKQ4X.js → chunk-XVPQNX7O.js} +89 -8
- package/dist/{chunk-YYZC2EQO.cjs → chunk-ZIE6EJGR.cjs} +23 -23
- 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 +7 -1
- package/dist/paint-editor/brush-model.d.ts +7 -1
- package/dist/paint-editor/controller.d.cts +52 -0
- package/dist/paint-editor/controller.d.ts +52 -0
- package/dist/paint-editor/index.cjs +850 -510
- package/dist/paint-editor/index.js +355 -15
- package/dist/paint-editor/ui.d.cts +5 -1
- package/dist/paint-editor/ui.d.ts +5 -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
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
mergeBrushPatch,
|
|
15
15
|
multiColorSliders,
|
|
16
16
|
patchBrushValue
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-IJ6NSWKM.js";
|
|
18
18
|
import {
|
|
19
19
|
createStickerTools,
|
|
20
20
|
describeStickerRef
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
BRUSH_PREVIEW_DARK_PAPER,
|
|
24
24
|
brushPreviewsOnDark
|
|
25
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-GHYJAMMS.js";
|
|
26
26
|
import {
|
|
27
27
|
toVideoFfmpeg
|
|
28
28
|
} from "../chunk-S2XPXA47.js";
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
resolveExternalAssets,
|
|
43
43
|
serializeLayers,
|
|
44
44
|
serializeLayersExternal
|
|
45
|
-
} from "../chunk-
|
|
45
|
+
} from "../chunk-XMSH66VU.js";
|
|
46
46
|
import "../chunk-ADMRNWR7.js";
|
|
47
47
|
import "../chunk-WJ4WQJCC.js";
|
|
48
48
|
import {
|
|
@@ -68,7 +68,7 @@ import "../chunk-ZIF4UJJ6.js";
|
|
|
68
68
|
import {
|
|
69
69
|
createPigmentTools,
|
|
70
70
|
pointerPressure
|
|
71
|
-
} from "../chunk-
|
|
71
|
+
} from "../chunk-JPB65KQ6.js";
|
|
72
72
|
import "../chunk-VWEWY4FY.js";
|
|
73
73
|
import "../chunk-HVQVHUTV.js";
|
|
74
74
|
import {
|
|
@@ -125,7 +125,7 @@ import {
|
|
|
125
125
|
wetPaperInput,
|
|
126
126
|
wetPigmentOf,
|
|
127
127
|
withStrokePath
|
|
128
|
-
} from "../chunk-
|
|
128
|
+
} from "../chunk-4EM5NGCL.js";
|
|
129
129
|
import {
|
|
130
130
|
BRUSH_ID,
|
|
131
131
|
BRUSH_PRESETS,
|
|
@@ -198,7 +198,7 @@ import {
|
|
|
198
198
|
readBrushSource,
|
|
199
199
|
resolveBrush,
|
|
200
200
|
usesPaintExchange
|
|
201
|
-
} from "../chunk-
|
|
201
|
+
} from "../chunk-XVPQNX7O.js";
|
|
202
202
|
import {
|
|
203
203
|
STAMP_KINDS,
|
|
204
204
|
StickersSlot,
|
|
@@ -248,15 +248,18 @@ import {
|
|
|
248
248
|
normalizeWetParams,
|
|
249
249
|
pigmentOf,
|
|
250
250
|
wetSupport
|
|
251
|
-
} from "../chunk-
|
|
252
|
-
import "../chunk-
|
|
251
|
+
} from "../chunk-CTHWXW5M.js";
|
|
252
|
+
import "../chunk-J23JOHPR.js";
|
|
253
253
|
import {
|
|
254
254
|
CoverageMap,
|
|
255
|
+
DEFAULT_LIVE_PATTERNS,
|
|
255
256
|
DEFAULT_PAINT_GRADIENT,
|
|
256
257
|
DEFAULT_PAINT_GRADIENT_MAPPING,
|
|
257
258
|
EMPTY_MIXER_LOAD,
|
|
258
259
|
GRAIN_PATTERNS,
|
|
259
260
|
GRAIN_TILE,
|
|
261
|
+
LIVE_PATTERN_KINDS,
|
|
262
|
+
LIVE_PATTERN_PRESETS,
|
|
260
263
|
MAX_BRUSH_SIZE,
|
|
261
264
|
PAINT_COLOR_JSON_SCHEMA,
|
|
262
265
|
PAINT_GRADIENT_FULL_SPEED,
|
|
@@ -288,6 +291,7 @@ import {
|
|
|
288
291
|
isGradientPaint,
|
|
289
292
|
loadMixer,
|
|
290
293
|
normalizeHexColor,
|
|
294
|
+
normalizeLivePatterns,
|
|
291
295
|
paintGradientMappingFor,
|
|
292
296
|
paintSourceColor,
|
|
293
297
|
paintSourceCss,
|
|
@@ -300,7 +304,7 @@ import {
|
|
|
300
304
|
scalePaintGradient,
|
|
301
305
|
solidPaint,
|
|
302
306
|
updatePaintGradientStop
|
|
303
|
-
} from "../chunk-
|
|
307
|
+
} from "../chunk-LDZOXESA.js";
|
|
304
308
|
import {
|
|
305
309
|
TileableNoise,
|
|
306
310
|
hash2,
|
|
@@ -5091,6 +5095,26 @@ async function replayPainting(source, target, options = {}) {
|
|
|
5091
5095
|
if (e.layerId && target.getLayer(e.layerId)) target.wetPaper({ layerId: e.layerId, rect: sr(d.rect), amount: d.amount });
|
|
5092
5096
|
break;
|
|
5093
5097
|
}
|
|
5098
|
+
case "live-patterns": {
|
|
5099
|
+
const d = e.data;
|
|
5100
|
+
if (e.layerId && target.getLayer(e.layerId)) {
|
|
5101
|
+
target.setLivePatterns(e.layerId, d ? { ...d, scale: Math.min(4, d.scale * s), enabled: true } : { enabled: false });
|
|
5102
|
+
}
|
|
5103
|
+
break;
|
|
5104
|
+
}
|
|
5105
|
+
case "seed-live-patterns": {
|
|
5106
|
+
const d = e.data;
|
|
5107
|
+
if (e.layerId && target.getLayer(e.layerId) && Array.isArray(d.points)) {
|
|
5108
|
+
target.seedLivePatterns({
|
|
5109
|
+
layerId: e.layerId,
|
|
5110
|
+
points: d.points.map((p) => ({ ...p, x: p.x * s, y: p.y * s })),
|
|
5111
|
+
radius: Math.min(512, d.radius * s),
|
|
5112
|
+
seed: d.seed,
|
|
5113
|
+
...d.settings ? { ...d.settings, ...d.settings.scale ? { scale: Math.min(4, d.settings.scale * s) } : {} } : {}
|
|
5114
|
+
});
|
|
5115
|
+
}
|
|
5116
|
+
break;
|
|
5117
|
+
}
|
|
5094
5118
|
case "ghost-release": {
|
|
5095
5119
|
const d = e.data;
|
|
5096
5120
|
if (e.layerId && target.getLayer(e.layerId)) target.wet.releaseGhost(e.layerId, d?.linger);
|
|
@@ -6410,6 +6434,16 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6410
6434
|
for (const [id, surface] of lights) if (findLayer(this.doc.layers, id)) light = withLayerLight(light, id, surface);
|
|
6411
6435
|
this.doc = { ...this.doc, ...light ? { light } : {} };
|
|
6412
6436
|
},
|
|
6437
|
+
layerHeight: (id) => this.doc.thick?.[id]?.height ?? null,
|
|
6438
|
+
updateHeights: (heights) => {
|
|
6439
|
+
let thick = this.doc.thick;
|
|
6440
|
+
for (const [id, height] of heights) {
|
|
6441
|
+
if (!findLayer(this.doc.layers, id)) continue;
|
|
6442
|
+
const prev = thick?.[id] ?? emptyThickChannels();
|
|
6443
|
+
thick = { ...thick ?? {}, [id]: { ...prev, height } };
|
|
6444
|
+
}
|
|
6445
|
+
if (thick !== this.doc.thick) this.doc = { ...this.doc, ...thick ? { thick } : {} };
|
|
6446
|
+
},
|
|
6413
6447
|
changed: () => {
|
|
6414
6448
|
}
|
|
6415
6449
|
},
|
|
@@ -6860,7 +6894,7 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
6860
6894
|
this.extensions = {};
|
|
6861
6895
|
this.guides = { ...this.guides, symmetry: { ...this.guides.symmetry, center: { x: next.canvas.width / 2, y: next.canvas.height / 2 } }, tracing: null };
|
|
6862
6896
|
this.tracingVersion++;
|
|
6863
|
-
if (this.wet.world) {
|
|
6897
|
+
if (this.wet.world || this.wet.patterns.size) {
|
|
6864
6898
|
this.beginWetOp();
|
|
6865
6899
|
this.wet.reset();
|
|
6866
6900
|
}
|
|
@@ -8823,7 +8857,19 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
8823
8857
|
s.result.wet = this.wet.isWet(s.layerId);
|
|
8824
8858
|
}
|
|
8825
8859
|
const l = this.getLayer(s.layerId);
|
|
8826
|
-
|
|
8860
|
+
let ch = s.thickChannels();
|
|
8861
|
+
if (wetStroke) {
|
|
8862
|
+
const f = this.wet.patterns.get(l.id);
|
|
8863
|
+
if (f?.enabled) {
|
|
8864
|
+
this.wet.settingsOf(l.id).livePatterns = { ...f.settings };
|
|
8865
|
+
if (f.settings.relief > 0 && f.tiles.size > 0) {
|
|
8866
|
+
const prevCh = ch ?? this.doc.thick?.[l.id] ?? emptyThickChannels();
|
|
8867
|
+
const nextHeight = f.applyReliefHeight(prevCh.height);
|
|
8868
|
+
if (nextHeight !== prevCh.height) ch = { ...prevCh, height: nextHeight };
|
|
8869
|
+
}
|
|
8870
|
+
}
|
|
8871
|
+
}
|
|
8872
|
+
const thick = withLayerThick(this.doc.thick, l.id, ch);
|
|
8827
8873
|
const sprayed = s.stickers();
|
|
8828
8874
|
const stickers = sprayed ? { ...this.doc.stickers ?? {}, [l.id]: [...this.doc.stickers?.[l.id] ?? [], ...sprayed] } : this.doc.stickers;
|
|
8829
8875
|
const wetLight = wetStroke && this.wet.world?.hasLane(l.id) ? this.wet.world.lightDisplay(l.id) : null;
|
|
@@ -8976,7 +9022,19 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
8976
9022
|
}
|
|
8977
9023
|
const l = findLayer(out.layers, s.layerId).layer;
|
|
8978
9024
|
const offset = s.init.wet ? { x: 0, y: 0 } : l.offset;
|
|
8979
|
-
|
|
9025
|
+
let ch = s.thickChannels();
|
|
9026
|
+
if (s.init.wet) {
|
|
9027
|
+
const f = this.wet.patterns.get(l.id);
|
|
9028
|
+
if (f?.enabled) {
|
|
9029
|
+
this.wet.settingsOf(l.id).livePatterns = { ...f.settings };
|
|
9030
|
+
if (f.settings.relief > 0 && f.tiles.size > 0) {
|
|
9031
|
+
const prevCh = ch ?? out.thick?.[l.id] ?? emptyThickChannels();
|
|
9032
|
+
const nextHeight = f.applyReliefHeight(prevCh.height);
|
|
9033
|
+
if (nextHeight !== prevCh.height) ch = { ...prevCh, height: nextHeight };
|
|
9034
|
+
}
|
|
9035
|
+
}
|
|
9036
|
+
}
|
|
9037
|
+
const thick = withLayerThick(out.thick, l.id, ch);
|
|
8980
9038
|
const sprayed = s.stickers();
|
|
8981
9039
|
const lit = s.lightChannel() ?? (s.init.wet && this.wet.world?.hasLane(l.id) ? this.wet.world.lightDisplay(l.id) : null);
|
|
8982
9040
|
const fl = s.fluorChannel();
|
|
@@ -9640,6 +9698,149 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
9640
9698
|
if (this.wet.busy) return [];
|
|
9641
9699
|
return this.wet.waterOverlay(rect);
|
|
9642
9700
|
}
|
|
9701
|
+
layerLivePatternsInfo(layerId) {
|
|
9702
|
+
const info = this.wet.info(layerId);
|
|
9703
|
+
const stats = this.wet.livePatternStats(layerId);
|
|
9704
|
+
return {
|
|
9705
|
+
layerId,
|
|
9706
|
+
wet: info.wet,
|
|
9707
|
+
wetCells: info.wetCells,
|
|
9708
|
+
wetBounds: info.wetBounds,
|
|
9709
|
+
...stats
|
|
9710
|
+
};
|
|
9711
|
+
}
|
|
9712
|
+
checkLivePatternsInput(input) {
|
|
9713
|
+
if (!input) return {};
|
|
9714
|
+
const out = {};
|
|
9715
|
+
if (input.pattern !== void 0) {
|
|
9716
|
+
if (!LIVE_PATTERN_KINDS.includes(input.pattern)) {
|
|
9717
|
+
throw new PaintEditorError(`pattern must be one of ${LIVE_PATTERN_KINDS.join(", ")}, not ${JSON.stringify(input.pattern)}.`);
|
|
9718
|
+
}
|
|
9719
|
+
out.pattern = input.pattern;
|
|
9720
|
+
}
|
|
9721
|
+
if (input.feed !== void 0) {
|
|
9722
|
+
if (!(Number.isFinite(input.feed) && input.feed >= 5e-3 && input.feed <= 0.1)) {
|
|
9723
|
+
throw new PaintEditorError(`feed ${input.feed} is out of range; use 0.005..0.1.`);
|
|
9724
|
+
}
|
|
9725
|
+
out.feed = input.feed;
|
|
9726
|
+
}
|
|
9727
|
+
if (input.kill !== void 0) {
|
|
9728
|
+
if (!(Number.isFinite(input.kill) && input.kill >= 0.02 && input.kill <= 0.08)) {
|
|
9729
|
+
throw new PaintEditorError(`kill ${input.kill} is out of range; use 0.02..0.08.`);
|
|
9730
|
+
}
|
|
9731
|
+
out.kill = input.kill;
|
|
9732
|
+
}
|
|
9733
|
+
if (input.scale !== void 0) {
|
|
9734
|
+
if (!(Number.isFinite(input.scale) && input.scale >= 0.25 && input.scale <= 4)) {
|
|
9735
|
+
throw new PaintEditorError(`scale ${input.scale} is out of range; use 0.25..4.`);
|
|
9736
|
+
}
|
|
9737
|
+
out.scale = input.scale;
|
|
9738
|
+
}
|
|
9739
|
+
if (input.contrast !== void 0) {
|
|
9740
|
+
if (!(Number.isFinite(input.contrast) && input.contrast >= 0 && input.contrast <= 2)) {
|
|
9741
|
+
throw new PaintEditorError(`contrast ${input.contrast} is out of range; use 0..2.`);
|
|
9742
|
+
}
|
|
9743
|
+
out.contrast = input.contrast;
|
|
9744
|
+
}
|
|
9745
|
+
if (input.secondColor !== void 0) {
|
|
9746
|
+
out.secondColor = input.secondColor === null ? null : parseColor(input.secondColor, "secondColor");
|
|
9747
|
+
}
|
|
9748
|
+
if (input.relief !== void 0) {
|
|
9749
|
+
if (!(Number.isFinite(input.relief) && input.relief >= 0 && input.relief <= 1)) {
|
|
9750
|
+
throw new PaintEditorError(`relief ${input.relief} is out of range; use 0..1.`);
|
|
9751
|
+
}
|
|
9752
|
+
out.relief = input.relief;
|
|
9753
|
+
}
|
|
9754
|
+
return out;
|
|
9755
|
+
}
|
|
9756
|
+
/**
|
|
9757
|
+
* Reads a layer's Gray-Scott reaction-diffusion live patterns (`layerId`, default the active
|
|
9758
|
+
* layer), plus all layers with wet paint or live patterns and the built-in Pearson presets.
|
|
9759
|
+
*/
|
|
9760
|
+
getLivePatterns(layerId) {
|
|
9761
|
+
const l = this.wetLayer(layerId, "read the live patterns of");
|
|
9762
|
+
const primary = this.layerLivePatternsInfo(l.id);
|
|
9763
|
+
const ids = /* @__PURE__ */ new Set([l.id, ...this.wet.wetLayerIds()]);
|
|
9764
|
+
for (const [id, f] of this.wet.patterns) {
|
|
9765
|
+
if ((f.enabled || f.tiles.size > 0) && findLayer(this.doc.layers, id)) ids.add(id);
|
|
9766
|
+
}
|
|
9767
|
+
for (const [id, s] of this.wet.settings) {
|
|
9768
|
+
if (s.livePatterns && findLayer(this.doc.layers, id)) ids.add(id);
|
|
9769
|
+
}
|
|
9770
|
+
const layers = [...ids].map((id) => id === l.id ? primary : this.layerLivePatternsInfo(id));
|
|
9771
|
+
return {
|
|
9772
|
+
...primary,
|
|
9773
|
+
layers,
|
|
9774
|
+
presets: LIVE_PATTERN_PRESETS,
|
|
9775
|
+
brushPresets: ["turing-wash", "coral-ink"]
|
|
9776
|
+
};
|
|
9777
|
+
}
|
|
9778
|
+
/**
|
|
9779
|
+
* Configures a layer's Gray-Scott reaction-diffusion live patterns (or clears them with
|
|
9780
|
+
* `enabled: false`). One undo step.
|
|
9781
|
+
*/
|
|
9782
|
+
setLivePatterns(layerId, update) {
|
|
9783
|
+
this.requireIdle("changing live patterns");
|
|
9784
|
+
this.requireWetIdle("changing live patterns");
|
|
9785
|
+
const l = this.wetLayer(layerId, "set the live patterns of");
|
|
9786
|
+
if (isLayerLocked(l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it first.`);
|
|
9787
|
+
if (update.enabled !== void 0 && typeof update.enabled !== "boolean") {
|
|
9788
|
+
throw new PaintEditorError("enabled must be true or false.");
|
|
9789
|
+
}
|
|
9790
|
+
const checked = this.checkLivePatternsInput(update);
|
|
9791
|
+
const before = this.doc;
|
|
9792
|
+
this.beginWetOp();
|
|
9793
|
+
const next = this.wet.setLivePatterns(l.id, update.enabled === false ? null : checked);
|
|
9794
|
+
this.logWet({ kind: "live-patterns", layerId: l.id, data: next });
|
|
9795
|
+
this.commit("Live patterns", this.withWetEvents(this.doc), before);
|
|
9796
|
+
return this.layerLivePatternsInfo(l.id);
|
|
9797
|
+
}
|
|
9798
|
+
/**
|
|
9799
|
+
* Seeds Gray-Scott reaction-diffusion activator (`V`) discs into a layer's live-pattern field so
|
|
9800
|
+
* patterns grow where the layer holds wet water and freeze where it dries. One undo step.
|
|
9801
|
+
*/
|
|
9802
|
+
seedLivePatterns(options) {
|
|
9803
|
+
this.requireIdle("seeding live patterns");
|
|
9804
|
+
this.requireWetIdle("seeding live patterns");
|
|
9805
|
+
const l = this.wetLayer(options.layerId, "seed live patterns on");
|
|
9806
|
+
if (isLayerLocked(l, "pixels")) throw new PaintEditorError(`Layer "${l.name}" has its pixels locked; unlock it first.`);
|
|
9807
|
+
if (!Array.isArray(options.points) || !options.points.length) {
|
|
9808
|
+
throw new PaintEditorError("points is empty; give at least one {x, y} in document pixels.");
|
|
9809
|
+
}
|
|
9810
|
+
const { width, height } = this.doc.canvas;
|
|
9811
|
+
const points = options.points.map((p, i) => {
|
|
9812
|
+
if (!p || !Number.isFinite(p.x) || !Number.isFinite(p.y)) {
|
|
9813
|
+
throw new PaintEditorError(`points[${i}] needs finite x and y in document pixels.`);
|
|
9814
|
+
}
|
|
9815
|
+
if (p.x < 0 || p.y < 0 || p.x >= width || p.y >= height) {
|
|
9816
|
+
throw new PaintEditorError(`points[${i}] (${p.x}, ${p.y}) is outside the ${width}\xD7${height} canvas.`);
|
|
9817
|
+
}
|
|
9818
|
+
if (p.strength !== void 0 && !(Number.isFinite(p.strength) && p.strength > 0 && p.strength <= 1)) {
|
|
9819
|
+
throw new PaintEditorError(`points[${i}].strength ${p.strength} is out of range; use above 0 up to 1.`);
|
|
9820
|
+
}
|
|
9821
|
+
return { x: p.x, y: p.y, ...p.strength !== void 0 ? { strength: p.strength } : {} };
|
|
9822
|
+
});
|
|
9823
|
+
const radius = options.radius ?? 16;
|
|
9824
|
+
if (!(Number.isFinite(radius) && radius >= 1 && radius <= 512)) {
|
|
9825
|
+
throw new PaintEditorError(`radius ${radius} is out of range; use 1..512 px.`);
|
|
9826
|
+
}
|
|
9827
|
+
const seed = options.seed ?? mix32(this.seedCounter++ * 2654435761 >>> 0) & 2147483647;
|
|
9828
|
+
if (!Number.isInteger(seed) || seed < 0) {
|
|
9829
|
+
throw new PaintEditorError(`seed ${seed} must be a whole number of 0 or more.`);
|
|
9830
|
+
}
|
|
9831
|
+
const hasSettings = options.pattern !== void 0 || options.feed !== void 0 || options.kill !== void 0 || options.scale !== void 0 || options.contrast !== void 0 || options.secondColor !== void 0 || options.relief !== void 0;
|
|
9832
|
+
const settings = hasSettings ? this.checkLivePatternsInput(options) : void 0;
|
|
9833
|
+
const before = this.doc;
|
|
9834
|
+
this.beginWetOp();
|
|
9835
|
+
const { seededCells } = this.wet.seedLivePatterns(l.id, points, radius, seed, settings);
|
|
9836
|
+
this.logWet({
|
|
9837
|
+
kind: "seed-live-patterns",
|
|
9838
|
+
layerId: l.id,
|
|
9839
|
+
data: { points, radius, seed, ...settings ? { settings } : {} }
|
|
9840
|
+
});
|
|
9841
|
+
this.commit("Seed live patterns", this.withWetEvents(this.doc), before);
|
|
9842
|
+
return { ...this.layerLivePatternsInfo(l.id), seededCells };
|
|
9843
|
+
}
|
|
9643
9844
|
// --- Rendering -----------------------------------------------------------------
|
|
9644
9845
|
sources() {
|
|
9645
9846
|
return { width: this.doc.canvas.width, height: this.doc.canvas.height };
|
|
@@ -9895,7 +10096,12 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
9895
10096
|
const savedGhost = ghost?.trigger === "agent" ? null : ghost;
|
|
9896
10097
|
const heldEvap = this.heldEvaporation.get(id);
|
|
9897
10098
|
const params = heldEvap !== void 0 ? { ...set.params, evaporation: heldEvap } : { ...set.params };
|
|
9898
|
-
layers[id] = {
|
|
10099
|
+
layers[id] = {
|
|
10100
|
+
params,
|
|
10101
|
+
flow: { ...set.flow },
|
|
10102
|
+
...savedGhost ? { ghost: savedGhost } : {},
|
|
10103
|
+
...set.livePatterns ? { livePatterns: { ...set.livePatterns } } : {}
|
|
10104
|
+
};
|
|
9899
10105
|
}
|
|
9900
10106
|
const flat = this.wet.tilt.angle === 0;
|
|
9901
10107
|
if (!Object.keys(layers).length && flat) return void 0;
|
|
@@ -9914,7 +10120,14 @@ var PaintEditorController = class _PaintEditorController {
|
|
|
9914
10120
|
}
|
|
9915
10121
|
const x = v;
|
|
9916
10122
|
const ghost = readWetGhost(x.ghost);
|
|
9917
|
-
|
|
10123
|
+
const livePatterns = x.livePatterns ? normalizeLivePatterns(x.livePatterns) : null;
|
|
10124
|
+
this.wet.settings.set(id, {
|
|
10125
|
+
params: normalizeWetParams(x.params ?? {}),
|
|
10126
|
+
flow: normalizeFlow(x.flow ?? {}),
|
|
10127
|
+
...ghost ? { ghost } : {},
|
|
10128
|
+
...livePatterns ? { livePatterns } : {}
|
|
10129
|
+
});
|
|
10130
|
+
if (livePatterns) this.wet.patternFieldOf(id).configure(livePatterns);
|
|
9918
10131
|
}
|
|
9919
10132
|
}
|
|
9920
10133
|
}
|
|
@@ -12102,6 +12315,9 @@ function shiftDocument(doc, dx, dy) {
|
|
|
12102
12315
|
if (e.kind === "dry" && typeof d.x === "number") return { ...e, data: moveRect(d, dx, dy) };
|
|
12103
12316
|
if (e.kind === "wet-paper" && d.rect) return { ...e, data: { ...d, rect: moveRect(d.rect, dx, dy) } };
|
|
12104
12317
|
if (e.kind === "flow" && d.center) return { ...e, data: { ...d, center: movePoint(d.center, dx, dy) } };
|
|
12318
|
+
if (e.kind === "seed-live-patterns" && Array.isArray(d.points)) {
|
|
12319
|
+
return { ...e, data: { ...d, points: d.points.map((p) => ({ ...p, x: p.x + dx, y: p.y + dy })) } };
|
|
12320
|
+
}
|
|
12105
12321
|
return e;
|
|
12106
12322
|
});
|
|
12107
12323
|
}
|
|
@@ -13139,6 +13355,43 @@ var WET_PARAM_SCHEMA = {
|
|
|
13139
13355
|
bloom: UNIT("Blooms: water running into a drying wash pushes its pigment into cauliflower edges (default 0.4)."),
|
|
13140
13356
|
bleed: UNIT("Colour bleed between touching wet areas (default 0.3).")
|
|
13141
13357
|
};
|
|
13358
|
+
var LIVE_PATTERN_SCHEMA = {
|
|
13359
|
+
pattern: {
|
|
13360
|
+
type: "string",
|
|
13361
|
+
enum: [...LIVE_PATTERN_KINDS],
|
|
13362
|
+
description: "Pearson Gray-Scott preset: spots, stripes, coral, maze or worms (default spots). Sets feed and kill unless explicit feed/kill are also passed."
|
|
13363
|
+
},
|
|
13364
|
+
feed: {
|
|
13365
|
+
type: "number",
|
|
13366
|
+
minimum: 5e-3,
|
|
13367
|
+
maximum: 0.1,
|
|
13368
|
+
description: "Gray-Scott feed rate F, 0.005..0.1 (default: the pattern preset\u2019s feed rate)."
|
|
13369
|
+
},
|
|
13370
|
+
kill: {
|
|
13371
|
+
type: "number",
|
|
13372
|
+
minimum: 0.02,
|
|
13373
|
+
maximum: 0.08,
|
|
13374
|
+
description: "Gray-Scott kill rate k, 0.02..0.08 (default: the pattern preset\u2019s kill rate)."
|
|
13375
|
+
},
|
|
13376
|
+
scale: {
|
|
13377
|
+
type: "number",
|
|
13378
|
+
minimum: 0.25,
|
|
13379
|
+
maximum: 4,
|
|
13380
|
+
description: "Diffusion scale 0.25..4 (larger values grow broader pattern features; default 1)."
|
|
13381
|
+
},
|
|
13382
|
+
contrast: {
|
|
13383
|
+
type: "number",
|
|
13384
|
+
minimum: 0,
|
|
13385
|
+
maximum: 2,
|
|
13386
|
+
description: "How strongly V modulates the wet pigment or blends toward secondColor, 0..2 (default 0.85)."
|
|
13387
|
+
},
|
|
13388
|
+
secondColor: {
|
|
13389
|
+
type: ["string", "null"],
|
|
13390
|
+
pattern: "^#[0-9a-fA-F]{6}$",
|
|
13391
|
+
description: "Optional #rrggbb colour that high-V pattern ridges blend toward, or null to modulate pigment contrast (default null)."
|
|
13392
|
+
},
|
|
13393
|
+
relief: UNIT("Impasto ridge height 0..1 written from V into the layer\u2019s thick height map so light catches the pattern (default 0).")
|
|
13394
|
+
};
|
|
13142
13395
|
function createPaintWetTools(c) {
|
|
13143
13396
|
const stillWet = () => c.wetState().wet;
|
|
13144
13397
|
return [
|
|
@@ -13302,6 +13555,73 @@ function createPaintWetTools(c) {
|
|
|
13302
13555
|
inputSchema: { type: "object", properties: { visible: { type: "boolean", description: "Show (true) or hide (false) the overlay." } }, required: ["visible"], additionalProperties: false },
|
|
13303
13556
|
annotations: { title: "Show the water", ...SET2 },
|
|
13304
13557
|
handler: ({ visible }) => ({ visible: c.setWaterOverlay(visible), stillWet: stillWet() })
|
|
13558
|
+
},
|
|
13559
|
+
{
|
|
13560
|
+
name: "get_live_patterns",
|
|
13561
|
+
title: "Get live patterns",
|
|
13562
|
+
description: "Reads the Gray-Scott reaction-diffusion live patterns on a layer (layerId, default the active layer): whether live patterns are enabled, the active settings (pattern, feed, kill, scale, contrast, secondColor, relief), activeTiles, patternCells, wetPatternCells (pattern cells still holding water where the pattern can grow), meanV, maxV, bounds, wet coverage (wet, wetCells, wetBounds), layers (every layer with wet paint or live patterns), and presets (built-in Pearson feed/kill presets: spots, stripes, coral, maze, worms). Call it before or after advance_wet_paint and dry_paint to inspect pattern growth and freezing.",
|
|
13563
|
+
inputSchema: { type: "object", properties: { layerId: LAYER_ID2 }, additionalProperties: false },
|
|
13564
|
+
annotations: { title: "Get live patterns", ...READ3 },
|
|
13565
|
+
coordinates: { out: ["wetBounds", "bounds", "layers[].wetBounds", "layers[].bounds"] },
|
|
13566
|
+
handler: ({ layerId }) => c.getLivePatterns(layerId)
|
|
13567
|
+
},
|
|
13568
|
+
{
|
|
13569
|
+
name: "set_live_patterns",
|
|
13570
|
+
title: "Set live patterns",
|
|
13571
|
+
description: "Configures a layer\u2019s Gray-Scott reaction-diffusion live patterns (or clears them with enabled: false). Patterns grow inside wet paint during advance_wet_paint and freeze when the paint dries (dry_paint). Choose a Pearson preset (spots, stripes, coral, maze, worms) or explicit feed and kill rates, scale, contrast, secondColor (#rrggbb or null to modulate pigment contrast) and relief (0..1, writes ridge height into thick paint so lighting catches the pattern). One undo step. Returns the layer\u2019s live-pattern stats and stillWet.",
|
|
13572
|
+
inputSchema: {
|
|
13573
|
+
type: "object",
|
|
13574
|
+
properties: {
|
|
13575
|
+
layerId: LAYER_ID2,
|
|
13576
|
+
enabled: { type: "boolean", description: "true (default) configures live patterns on the layer; false clears them." },
|
|
13577
|
+
...LIVE_PATTERN_SCHEMA
|
|
13578
|
+
},
|
|
13579
|
+
additionalProperties: false
|
|
13580
|
+
},
|
|
13581
|
+
annotations: { title: "Set live patterns", ...SET2 },
|
|
13582
|
+
coordinates: { out: ["wetBounds", "bounds"] },
|
|
13583
|
+
handler: async ({ layerId, ...update }) => {
|
|
13584
|
+
await c.wetIdle();
|
|
13585
|
+
return { ...c.setLivePatterns(layerId, update), stillWet: stillWet() };
|
|
13586
|
+
}
|
|
13587
|
+
},
|
|
13588
|
+
{
|
|
13589
|
+
name: "seed_live_patterns",
|
|
13590
|
+
title: "Seed live patterns",
|
|
13591
|
+
description: 'Seeds Gray-Scott reaction-diffusion activator (V) discs at points on a layer so reaction-diffusion patterns (spots, stripes, coral, maze, worms) grow where the layer holds wet water (advance_wet_paint) and freeze where it dries (dry_paint). Painting with a wet brush that has a livePatterns facet (such as preset "turing-wash" or "coral-ink") also seeds along the stroke automatically. One undo step. Returns seededCells, the layer\u2019s live-pattern stats (patternCells, wetPatternCells, meanV, maxV, bounds) and stillWet.',
|
|
13592
|
+
inputSchema: {
|
|
13593
|
+
type: "object",
|
|
13594
|
+
properties: {
|
|
13595
|
+
layerId: LAYER_ID2,
|
|
13596
|
+
points: {
|
|
13597
|
+
type: "array",
|
|
13598
|
+
minItems: 1,
|
|
13599
|
+
maxItems: 1024,
|
|
13600
|
+
description: "Seed centres in document pixels where reaction-diffusion activator V is nucleated.",
|
|
13601
|
+
items: {
|
|
13602
|
+
type: "object",
|
|
13603
|
+
properties: {
|
|
13604
|
+
x: { type: "number", description: "Document x in pixels." },
|
|
13605
|
+
y: { type: "number", description: "Document y in pixels." },
|
|
13606
|
+
strength: { type: "number", exclusiveMinimum: 0, maximum: 1, description: "Seed strength 0..1 (default 1)." }
|
|
13607
|
+
},
|
|
13608
|
+
required: ["x", "y"],
|
|
13609
|
+
additionalProperties: false
|
|
13610
|
+
}
|
|
13611
|
+
},
|
|
13612
|
+
radius: { type: "number", minimum: 1, maximum: 512, description: "Seed disc radius in document pixels (default 16)." },
|
|
13613
|
+
seed: { type: "integer", minimum: 0, description: "Deterministic noise seed for the nucleated discs (default: next editor seed)." },
|
|
13614
|
+
...LIVE_PATTERN_SCHEMA
|
|
13615
|
+
},
|
|
13616
|
+
required: ["points"],
|
|
13617
|
+
additionalProperties: false
|
|
13618
|
+
},
|
|
13619
|
+
annotations: { title: "Seed live patterns", ...WRITE3 },
|
|
13620
|
+
coordinates: { in: ["points"], out: ["wetBounds", "bounds"] },
|
|
13621
|
+
handler: async (args) => {
|
|
13622
|
+
await c.wetIdle();
|
|
13623
|
+
return { ...c.seedLivePatterns(args), stillWet: stillWet() };
|
|
13624
|
+
}
|
|
13305
13625
|
}
|
|
13306
13626
|
];
|
|
13307
13627
|
}
|
|
@@ -15435,6 +15755,18 @@ var WET_TILT_SLIDERS = [
|
|
|
15435
15755
|
{ path: "direction", label: "Downhill", min: 0, max: 359, step: 1 }
|
|
15436
15756
|
];
|
|
15437
15757
|
var WET_SPEED_SLIDER = { path: "speed", label: "Speed", min: 15, max: 480, step: 15 };
|
|
15758
|
+
var LIVE_PATTERN_LABELS = {
|
|
15759
|
+
spots: "Spots",
|
|
15760
|
+
stripes: "Stripes",
|
|
15761
|
+
coral: "Coral",
|
|
15762
|
+
maze: "Maze",
|
|
15763
|
+
worms: "Worms"
|
|
15764
|
+
};
|
|
15765
|
+
var LIVE_PATTERN_SLIDERS = [
|
|
15766
|
+
{ path: "scale", label: "Scale", min: 0.25, max: 4, step: 0.05 },
|
|
15767
|
+
{ path: "contrast", label: "Contrast", min: 0, max: 2, step: 0.05 },
|
|
15768
|
+
{ path: "relief", label: "Relief", min: 0, max: 1, step: 0.01 }
|
|
15769
|
+
];
|
|
15438
15770
|
var WET_GPU_OPTIONS = [
|
|
15439
15771
|
{ value: "auto", label: "GPU for large washes" },
|
|
15440
15772
|
{ value: "off", label: "CPU only" }
|
|
@@ -16108,13 +16440,14 @@ function uiTables() {
|
|
|
16108
16440
|
brushOptions: BRUSH_OPTION_CONTROLS,
|
|
16109
16441
|
blendMenu: BLEND_MENU_GROUPS,
|
|
16110
16442
|
layerEffects: LAYER_EFFECT_MENU.map(({ kind, label }) => ({ kind, label, controls: layerEffectControls(defaultLayerEffect(kind, kind)) })),
|
|
16111
|
-
sliders: { paper: PAPER_SLIDERS, wet: WET_PARAM_SLIDERS, wetTilt: WET_TILT_SLIDERS, wetSpeed: WET_SPEED_SLIDER, light: LIGHT_SLIDERS, uvLight: UV_LIGHT_SLIDERS, viewTilt: VIEW_TILT_SLIDERS, ghost: GHOST_SLIDERS, mutation: MUTATION_SLIDERS, stroke: STROKE_SLIDERS, sticker: STICKER_SLIDERS },
|
|
16443
|
+
sliders: { paper: PAPER_SLIDERS, wet: WET_PARAM_SLIDERS, wetTilt: WET_TILT_SLIDERS, wetSpeed: WET_SPEED_SLIDER, light: LIGHT_SLIDERS, uvLight: UV_LIGHT_SLIDERS, viewTilt: VIEW_TILT_SLIDERS, ghost: GHOST_SLIDERS, mutation: MUTATION_SLIDERS, livePatterns: LIVE_PATTERN_SLIDERS, stroke: STROKE_SLIDERS, sticker: STICKER_SLIDERS },
|
|
16112
16444
|
pathStrokeTapers: PATH_STROKE_TAPERS,
|
|
16113
16445
|
padSampleSizes: PAD_SAMPLE_SIZES,
|
|
16114
16446
|
wetGpu: WET_GPU_OPTIONS,
|
|
16115
16447
|
labels: {
|
|
16116
16448
|
wetTools: WET_TOOL_LABELS,
|
|
16117
16449
|
wetMedia: WET_MEDIUM_LABELS,
|
|
16450
|
+
livePatterns: LIVE_PATTERN_LABELS,
|
|
16118
16451
|
impastoTools: IMPASTO_TOOL_LABELS,
|
|
16119
16452
|
particleKinds: PARTICLE_KIND_LABELS,
|
|
16120
16453
|
particleRenders: PARTICLE_RENDER_LABELS,
|
|
@@ -16191,6 +16524,7 @@ export {
|
|
|
16191
16524
|
DEFAULT_IRIDESCENCE,
|
|
16192
16525
|
DEFAULT_LIGHT,
|
|
16193
16526
|
DEFAULT_LIGHTING,
|
|
16527
|
+
DEFAULT_LIVE_PATTERNS,
|
|
16194
16528
|
DEFAULT_MULTI_COLOR,
|
|
16195
16529
|
DEFAULT_MUTATION,
|
|
16196
16530
|
DEFAULT_MUTATION_RATES,
|
|
@@ -16235,6 +16569,11 @@ export {
|
|
|
16235
16569
|
IMPASTO_TOOL_LABELS,
|
|
16236
16570
|
IRIDESCENCE_SLIDERS,
|
|
16237
16571
|
LIGHT_SLIDERS,
|
|
16572
|
+
LIVE_PATTERN_KINDS,
|
|
16573
|
+
LIVE_PATTERN_LABELS,
|
|
16574
|
+
LIVE_PATTERN_PRESETS,
|
|
16575
|
+
LIVE_PATTERN_SCHEMA,
|
|
16576
|
+
LIVE_PATTERN_SLIDERS,
|
|
16238
16577
|
LIVE_STROKE_ENGINES,
|
|
16239
16578
|
LitCache,
|
|
16240
16579
|
MAX_BRUSH_SIZE,
|
|
@@ -16482,6 +16821,7 @@ export {
|
|
|
16482
16821
|
normalizeImpasto,
|
|
16483
16822
|
normalizeLight,
|
|
16484
16823
|
normalizeLighting,
|
|
16824
|
+
normalizeLivePatterns,
|
|
16485
16825
|
normalizeMultiColor,
|
|
16486
16826
|
normalizeMutation,
|
|
16487
16827
|
normalizeMutationRates,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { MixerLoad } from '../paint/exchange.cjs';
|
|
12
12
|
import { type BlendModeInfo } from '../raster/blend.cjs';
|
|
13
|
-
import type { ImpastoTool, WetMediumKind, WetTool } from './brushes.cjs';
|
|
13
|
+
import type { ImpastoTool, WetMediumKind, WetTool, LivePatternKind } from './brushes.cjs';
|
|
14
14
|
import type { FillRegionOptions, PaintEditorController } from './controller.cjs';
|
|
15
15
|
import type { PenPoint } from './engine.cjs';
|
|
16
16
|
import { type Point2 } from './guides.cjs';
|
|
@@ -204,6 +204,10 @@ export declare const WET_PARAM_SLIDERS: readonly SliderControl[];
|
|
|
204
204
|
export declare const WET_TILT_SLIDERS: readonly SliderControl[];
|
|
205
205
|
/** The speed slider (steps per second). */
|
|
206
206
|
export declare const WET_SPEED_SLIDER: SliderControl;
|
|
207
|
+
/** Labels of the Gray-Scott live pattern kinds. */
|
|
208
|
+
export declare const LIVE_PATTERN_LABELS: Readonly<Record<LivePatternKind, string>>;
|
|
209
|
+
/** The wet panel's sliders for a layer's live patterns. */
|
|
210
|
+
export declare const LIVE_PATTERN_SLIDERS: readonly SliderControl[];
|
|
207
211
|
/** The wet-engine choices a panel offers (Engine B, the WebGPU accelerator). */
|
|
208
212
|
export declare const WET_GPU_OPTIONS: readonly {
|
|
209
213
|
value: WetGpuMode;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { MixerLoad } from '../paint/exchange.js';
|
|
12
12
|
import { type BlendModeInfo } from '../raster/blend.js';
|
|
13
|
-
import type { ImpastoTool, WetMediumKind, WetTool } from './brushes.js';
|
|
13
|
+
import type { ImpastoTool, WetMediumKind, WetTool, LivePatternKind } from './brushes.js';
|
|
14
14
|
import type { FillRegionOptions, PaintEditorController } from './controller.js';
|
|
15
15
|
import type { PenPoint } from './engine.js';
|
|
16
16
|
import { type Point2 } from './guides.js';
|
|
@@ -204,6 +204,10 @@ export declare const WET_PARAM_SLIDERS: readonly SliderControl[];
|
|
|
204
204
|
export declare const WET_TILT_SLIDERS: readonly SliderControl[];
|
|
205
205
|
/** The speed slider (steps per second). */
|
|
206
206
|
export declare const WET_SPEED_SLIDER: SliderControl;
|
|
207
|
+
/** Labels of the Gray-Scott live pattern kinds. */
|
|
208
|
+
export declare const LIVE_PATTERN_LABELS: Readonly<Record<LivePatternKind, string>>;
|
|
209
|
+
/** The wet panel's sliders for a layer's live patterns. */
|
|
210
|
+
export declare const LIVE_PATTERN_SLIDERS: readonly SliderControl[];
|
|
207
211
|
/** The wet-engine choices a panel offers (Engine B, the WebGPU accelerator). */
|
|
208
212
|
export declare const WET_GPU_OPTIONS: readonly {
|
|
209
213
|
value: WetGpuMode;
|
|
@@ -63,4 +63,46 @@ export declare const WET_PARAM_SCHEMA: {
|
|
|
63
63
|
readonly description: string;
|
|
64
64
|
};
|
|
65
65
|
};
|
|
66
|
+
export declare const LIVE_PATTERN_SCHEMA: {
|
|
67
|
+
readonly pattern: {
|
|
68
|
+
readonly type: "string";
|
|
69
|
+
readonly enum: readonly ["spots", "stripes", "coral", "maze", "worms"];
|
|
70
|
+
readonly description: "Pearson Gray-Scott preset: spots, stripes, coral, maze or worms (default spots). Sets feed and kill unless explicit feed/kill are also passed.";
|
|
71
|
+
};
|
|
72
|
+
readonly feed: {
|
|
73
|
+
readonly type: "number";
|
|
74
|
+
readonly minimum: 0.005;
|
|
75
|
+
readonly maximum: 0.1;
|
|
76
|
+
readonly description: "Gray-Scott feed rate F, 0.005..0.1 (default: the pattern preset’s feed rate).";
|
|
77
|
+
};
|
|
78
|
+
readonly kill: {
|
|
79
|
+
readonly type: "number";
|
|
80
|
+
readonly minimum: 0.02;
|
|
81
|
+
readonly maximum: 0.08;
|
|
82
|
+
readonly description: "Gray-Scott kill rate k, 0.02..0.08 (default: the pattern preset’s kill rate).";
|
|
83
|
+
};
|
|
84
|
+
readonly scale: {
|
|
85
|
+
readonly type: "number";
|
|
86
|
+
readonly minimum: 0.25;
|
|
87
|
+
readonly maximum: 4;
|
|
88
|
+
readonly description: "Diffusion scale 0.25..4 (larger values grow broader pattern features; default 1).";
|
|
89
|
+
};
|
|
90
|
+
readonly contrast: {
|
|
91
|
+
readonly type: "number";
|
|
92
|
+
readonly minimum: 0;
|
|
93
|
+
readonly maximum: 2;
|
|
94
|
+
readonly description: "How strongly V modulates the wet pigment or blends toward secondColor, 0..2 (default 0.85).";
|
|
95
|
+
};
|
|
96
|
+
readonly secondColor: {
|
|
97
|
+
readonly type: readonly ["string", "null"];
|
|
98
|
+
readonly pattern: "^#[0-9a-fA-F]{6}$";
|
|
99
|
+
readonly description: "Optional #rrggbb colour that high-V pattern ridges blend toward, or null to modulate pigment contrast (default null).";
|
|
100
|
+
};
|
|
101
|
+
readonly relief: {
|
|
102
|
+
readonly type: "number";
|
|
103
|
+
readonly minimum: 0;
|
|
104
|
+
readonly maximum: 1;
|
|
105
|
+
readonly description: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
66
108
|
export declare function createPaintWetTools(c: PaintEditorController): PaintAgentTool[];
|