@pibbl/core 0.0.2 → 0.0.3-alpha.90.1
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/THIRD_PARTY_NOTICES.txt +81 -0
- package/dist/features/textures/index.d.ts +12 -2
- package/dist/features/textures/index.js +33 -1
- package/dist/features/textures/index.js.map +2 -2
- package/dist/features/textures/lib/chemical-field.d.ts +56 -0
- package/dist/features/textures/lib/chemical-field.js +154 -0
- package/dist/features/textures/lib/chemical-field.js.map +7 -0
- package/dist/features/textures/lib/chemical-recipes.d.ts +119 -0
- package/dist/features/textures/lib/chemical-recipes.js +275 -0
- package/dist/features/textures/lib/chemical-recipes.js.map +7 -0
- package/dist/features/textures/lib/definitions.d.ts +3 -18
- package/dist/features/textures/lib/definitions.js +15 -20
- package/dist/features/textures/lib/definitions.js.map +2 -2
- package/dist/features/textures/lib/geometric-patterns.d.ts +149 -0
- package/dist/features/textures/lib/geometric-patterns.js +305 -0
- package/dist/features/textures/lib/geometric-patterns.js.map +7 -0
- package/dist/features/textures/lib/gray-scott.d.ts +55 -0
- package/dist/features/textures/lib/gray-scott.js +39 -0
- package/dist/features/textures/lib/gray-scott.js.map +7 -0
- package/dist/features/textures/lib/patterns.d.ts +123 -0
- package/dist/features/textures/lib/patterns.js +344 -0
- package/dist/features/textures/lib/patterns.js.map +7 -0
- package/dist/features/textures/lib/reaction-diffusion.d.ts +3 -2
- package/dist/features/textures/lib/reaction-diffusion.js +9 -20
- package/dist/features/textures/lib/reaction-diffusion.js.map +2 -2
- package/dist/features/textures/lib/simulation.d.ts +10 -4
- package/dist/features/textures/lib/simulation.js +23 -13
- package/dist/features/textures/lib/simulation.js.map +2 -2
- package/dist/features/viz/index.d.ts +68 -6
- package/dist/features/viz/index.js +164 -2
- package/dist/features/viz/index.js.map +2 -2
- package/dist/features/viz/inspection/bar.d.ts +79 -0
- package/dist/features/viz/inspection/bar.js +49 -0
- package/dist/features/viz/inspection/bar.js.map +7 -0
- package/dist/features/viz/inspection/candle.d.ts +156 -0
- package/dist/features/viz/inspection/candle.js +120 -0
- package/dist/features/viz/inspection/candle.js.map +7 -0
- package/dist/features/viz/inspection/capture-types.d.ts +65 -0
- package/dist/features/viz/inspection/capture.d.ts +16 -0
- package/dist/features/viz/inspection/capture.js +49 -0
- package/dist/features/viz/inspection/capture.js.map +7 -0
- package/dist/features/viz/inspection/handler.d.ts +36 -0
- package/dist/features/viz/inspection/handler.js +91 -0
- package/dist/features/viz/inspection/handler.js.map +7 -0
- package/dist/features/viz/inspection/ohlc-bar.d.ts +132 -0
- package/dist/features/viz/inspection/ohlc-bar.js +118 -0
- package/dist/features/viz/inspection/ohlc-bar.js.map +7 -0
- package/dist/features/viz/inspection/owned-ref.d.ts +16 -0
- package/dist/features/viz/inspection/owned-ref.js +99 -0
- package/dist/features/viz/inspection/owned-ref.js.map +7 -0
- package/dist/features/viz/inspection/painted-point.d.ts +22 -0
- package/dist/features/viz/inspection/painted-point.js +29 -0
- package/dist/features/viz/inspection/painted-point.js.map +7 -0
- package/dist/features/viz/inspection/queries.d.ts +100 -0
- package/dist/features/viz/inspection/queries.js +192 -0
- package/dist/features/viz/inspection/queries.js.map +7 -0
- package/dist/features/viz/inspection/query-types.d.ts +177 -0
- package/dist/features/viz/inspection/volume.d.ts +104 -0
- package/dist/features/viz/inspection/volume.js +95 -0
- package/dist/features/viz/inspection/volume.js.map +7 -0
- package/dist/features/viz/inspection.d.ts +19 -0
- package/dist/features/viz/inspection.js +54 -0
- package/dist/features/viz/inspection.js.map +7 -0
- package/dist/features/viz/inspection.mjs +1 -0
- package/dist/features/viz/lib/area-series.d.ts +62 -0
- package/dist/features/viz/lib/area-series.js +120 -0
- package/dist/features/viz/lib/area-series.js.map +7 -0
- package/dist/features/viz/lib/axis.js +1 -1
- package/dist/features/viz/lib/axis.js.map +2 -2
- package/dist/features/viz/lib/bar-series.d.ts +3 -1
- package/dist/features/viz/lib/bar-series.js +16 -1
- package/dist/features/viz/lib/bar-series.js.map +2 -2
- package/dist/features/viz/lib/baseline-series.d.ts +55 -0
- package/dist/features/viz/lib/baseline-series.js +136 -0
- package/dist/features/viz/lib/baseline-series.js.map +7 -0
- package/dist/features/viz/lib/candlestick-series.d.ts +62 -0
- package/dist/features/viz/lib/candlestick-series.js +150 -0
- package/dist/features/viz/lib/candlestick-series.js.map +7 -0
- package/dist/features/viz/lib/censored-point-series.d.ts +71 -0
- package/dist/features/viz/lib/censored-point-series.js +129 -0
- package/dist/features/viz/lib/censored-point-series.js.map +7 -0
- package/dist/features/viz/lib/color-context.d.ts +4 -0
- package/dist/features/viz/lib/color-context.js +41 -0
- package/dist/features/viz/lib/color-context.js.map +7 -0
- package/dist/features/viz/lib/color-math.d.ts +4 -0
- package/dist/features/viz/lib/color-math.js +31 -0
- package/dist/features/viz/lib/color-math.js.map +7 -0
- package/dist/features/viz/lib/color-types.d.ts +53 -0
- package/dist/features/viz/lib/curve-definition.d.ts +49 -0
- package/dist/features/viz/lib/curve-definition.js +148 -0
- package/dist/features/viz/lib/curve-definition.js.map +7 -0
- package/dist/features/viz/lib/diverging-color-scale.d.ts +11 -0
- package/dist/features/viz/lib/diverging-color-scale.js +51 -0
- package/dist/features/viz/lib/diverging-color-scale.js.map +7 -0
- package/dist/features/viz/lib/domain-navigation.d.ts +40 -0
- package/dist/features/viz/lib/domain-navigation.js +77 -0
- package/dist/features/viz/lib/domain-navigation.js.map +7 -0
- package/dist/features/viz/lib/editable-chart-elements.d.ts +178 -0
- package/dist/features/viz/lib/editable-chart-elements.js +733 -0
- package/dist/features/viz/lib/editable-chart-elements.js.map +7 -0
- package/dist/features/viz/lib/financial-aggregation.d.ts +127 -0
- package/dist/features/viz/lib/financial-aggregation.js +116 -0
- package/dist/features/viz/lib/financial-aggregation.js.map +7 -0
- package/dist/features/viz/lib/financial-autoscale.d.ts +64 -0
- package/dist/features/viz/lib/financial-autoscale.js +61 -0
- package/dist/features/viz/lib/financial-autoscale.js.map +7 -0
- package/dist/features/viz/lib/financial-comparison.d.ts +62 -0
- package/dist/features/viz/lib/financial-comparison.js +98 -0
- package/dist/features/viz/lib/financial-comparison.js.map +7 -0
- package/dist/features/viz/lib/financial-geometry.d.ts +77 -0
- package/dist/features/viz/lib/financial-geometry.js +67 -0
- package/dist/features/viz/lib/financial-geometry.js.map +7 -0
- package/dist/features/viz/lib/financial-indicators.d.ts +114 -0
- package/dist/features/viz/lib/financial-indicators.js +135 -0
- package/dist/features/viz/lib/financial-indicators.js.map +7 -0
- package/dist/features/viz/lib/financial-oscillators.d.ts +171 -0
- package/dist/features/viz/lib/financial-oscillators.js +265 -0
- package/dist/features/viz/lib/financial-oscillators.js.map +7 -0
- package/dist/features/viz/lib/graph/bipartite.d.ts +14 -0
- package/dist/features/viz/lib/graph/bipartite.js +250 -0
- package/dist/features/viz/lib/graph/bipartite.js.map +7 -0
- package/dist/features/viz/lib/graph/chord.d.ts +44 -0
- package/dist/features/viz/lib/graph/chord.js +348 -0
- package/dist/features/viz/lib/graph/chord.js.map +7 -0
- package/dist/features/viz/lib/graph/dependency.d.ts +26 -0
- package/dist/features/viz/lib/graph/dependency.js +141 -0
- package/dist/features/viz/lib/graph/dependency.js.map +7 -0
- package/dist/features/viz/lib/graph/force.d.ts +28 -0
- package/dist/features/viz/lib/graph/force.js +580 -0
- package/dist/features/viz/lib/graph/force.js.map +7 -0
- package/dist/features/viz/lib/graph/hierarchy.d.ts +21 -0
- package/dist/features/viz/lib/graph/hierarchy.js +112 -0
- package/dist/features/viz/lib/graph/hierarchy.js.map +7 -0
- package/dist/features/viz/lib/graph/icicle.d.ts +16 -0
- package/dist/features/viz/lib/graph/icicle.js +153 -0
- package/dist/features/viz/lib/graph/icicle.js.map +7 -0
- package/dist/features/viz/lib/graph/matrix.d.ts +30 -0
- package/dist/features/viz/lib/graph/matrix.js +243 -0
- package/dist/features/viz/lib/graph/matrix.js.map +7 -0
- package/dist/features/viz/lib/graph/neighborhood.d.ts +11 -0
- package/dist/features/viz/lib/graph/neighborhood.js +281 -0
- package/dist/features/viz/lib/graph/neighborhood.js.map +7 -0
- package/dist/features/viz/lib/graph/routes.d.ts +35 -0
- package/dist/features/viz/lib/graph/routes.js +102 -0
- package/dist/features/viz/lib/graph/routes.js.map +7 -0
- package/dist/features/viz/lib/graph/sankey.d.ts +44 -0
- package/dist/features/viz/lib/graph/sankey.js +341 -0
- package/dist/features/viz/lib/graph/sankey.js.map +7 -0
- package/dist/features/viz/lib/graph/shared.d.ts +59 -0
- package/dist/features/viz/lib/graph/shared.js +296 -0
- package/dist/features/viz/lib/graph/shared.js.map +7 -0
- package/dist/features/viz/lib/graph/tree.d.ts +11 -0
- package/dist/features/viz/lib/graph/tree.js +232 -0
- package/dist/features/viz/lib/graph/tree.js.map +7 -0
- package/dist/features/viz/lib/graph/treemap.d.ts +20 -0
- package/dist/features/viz/lib/graph/treemap.js +227 -0
- package/dist/features/viz/lib/graph/treemap.js.map +7 -0
- package/dist/features/viz/lib/graph/types.d.ts +1097 -0
- package/dist/features/viz/lib/hover-data.d.ts +1 -1
- package/dist/features/viz/lib/hover-data.js +5 -2
- package/dist/features/viz/lib/hover-data.js.map +2 -2
- package/dist/features/viz/lib/interval-band-series.d.ts +49 -0
- package/dist/features/viz/lib/interval-band-series.js +136 -0
- package/dist/features/viz/lib/interval-band-series.js.map +7 -0
- package/dist/features/viz/lib/interval-diamond-series.d.ts +43 -0
- package/dist/features/viz/lib/interval-diamond-series.js +124 -0
- package/dist/features/viz/lib/interval-diamond-series.js.map +7 -0
- package/dist/features/viz/lib/interval-series.d.ts +79 -0
- package/dist/features/viz/lib/interval-series.js +158 -0
- package/dist/features/viz/lib/interval-series.js.map +7 -0
- package/dist/features/viz/lib/line-series.d.ts +1 -1
- package/dist/features/viz/lib/line-series.js +47 -28
- package/dist/features/viz/lib/line-series.js.map +2 -2
- package/dist/features/viz/lib/linear-scale.js +1 -1
- package/dist/features/viz/lib/linear-scale.js.map +2 -2
- package/dist/features/viz/lib/monotone-curve.d.ts +11 -0
- package/dist/features/viz/lib/monotone-curve.js +63 -0
- package/dist/features/viz/lib/monotone-curve.js.map +7 -0
- package/dist/features/viz/lib/numeric-range-interpolation.d.ts +15 -0
- package/dist/features/viz/lib/numeric-range-interpolation.js +36 -0
- package/dist/features/viz/lib/numeric-range-interpolation.js.map +7 -0
- package/dist/features/viz/lib/ohlc-bar-series.d.ts +55 -0
- package/dist/features/viz/lib/ohlc-bar-series.js +168 -0
- package/dist/features/viz/lib/ohlc-bar-series.js.map +7 -0
- package/dist/features/viz/lib/paired-series.d.ts +44 -0
- package/dist/features/viz/lib/paired-series.js +93 -0
- package/dist/features/viz/lib/paired-series.js.map +7 -0
- package/dist/features/viz/lib/plot-series.js +11 -6
- package/dist/features/viz/lib/plot-series.js.map +2 -2
- package/dist/features/viz/lib/plot-types.d.ts +4 -3
- package/dist/features/viz/lib/point-series.d.ts +1 -1
- package/dist/features/viz/lib/point-series.js +36 -9
- package/dist/features/viz/lib/point-series.js.map +2 -2
- package/dist/features/viz/lib/point-types.d.ts +5 -2
- package/dist/features/viz/lib/scale-context.d.ts +1 -1
- package/dist/features/viz/lib/scale-ticks.js +21 -6
- package/dist/features/viz/lib/scale-ticks.js.map +2 -2
- package/dist/features/viz/lib/sequential-color-scale.d.ts +11 -0
- package/dist/features/viz/lib/sequential-color-scale.js +49 -0
- package/dist/features/viz/lib/sequential-color-scale.js.map +7 -0
- package/dist/features/viz/lib/series-position.d.ts +12 -0
- package/dist/features/viz/lib/series-position.js +44 -0
- package/dist/features/viz/lib/series-position.js.map +7 -0
- package/dist/features/viz/lib/step-curves.d.ts +19 -0
- package/dist/features/viz/lib/step-curves.js +53 -0
- package/dist/features/viz/lib/step-curves.js.map +7 -0
- package/dist/features/viz/lib/threshold-color-scale.d.ts +43 -0
- package/dist/features/viz/lib/threshold-color-scale.js +59 -0
- package/dist/features/viz/lib/threshold-color-scale.js.map +7 -0
- package/dist/features/viz/lib/trading-time-mapping.d.ts +32 -0
- package/dist/features/viz/lib/trading-time-mapping.js +89 -0
- package/dist/features/viz/lib/trading-time-mapping.js.map +7 -0
- package/dist/features/viz/lib/trading-time-scale.d.ts +83 -0
- package/dist/features/viz/lib/trading-time-scale.js +96 -0
- package/dist/features/viz/lib/trading-time-scale.js.map +7 -0
- package/dist/features/viz/lib/trajectory-series.d.ts +71 -0
- package/dist/features/viz/lib/trajectory-series.js +111 -0
- package/dist/features/viz/lib/trajectory-series.js.map +7 -0
- package/dist/features/viz/lib/types.d.ts +20 -4
- package/dist/features/viz/lib/use-continuous-scale.js +6 -1
- package/dist/features/viz/lib/use-continuous-scale.js.map +2 -2
- package/dist/features/viz/lib/volume-series.d.ts +59 -0
- package/dist/features/viz/lib/volume-series.js +117 -0
- package/dist/features/viz/lib/volume-series.js.map +7 -0
- package/dist/features/viz/lib/weighted-point-series.d.ts +71 -0
- package/dist/features/viz/lib/weighted-point-series.js +169 -0
- package/dist/features/viz/lib/weighted-point-series.js.map +7 -0
- package/dist/filters/backdrop-contrast-gpu.d.ts +5 -0
- package/dist/filters/backdrop-contrast-gpu.js +33 -0
- package/dist/filters/backdrop-contrast-gpu.js.map +7 -0
- package/dist/filters/backdrop-contrast.d.ts +21 -0
- package/dist/filters/backdrop-contrast.js +61 -0
- package/dist/filters/backdrop-contrast.js.map +7 -0
- package/dist/filters/emboss-gpu.d.ts +4 -0
- package/dist/filters/emboss-gpu.js +39 -0
- package/dist/filters/emboss-gpu.js.map +7 -0
- package/dist/filters/emboss.d.ts +32 -0
- package/dist/filters/emboss.js +106 -0
- package/dist/filters/emboss.js.map +7 -0
- package/dist/filters/filter-executor.d.ts +11 -4
- package/dist/filters/filter-executor.js +104 -49
- package/dist/filters/filter-executor.js.map +2 -2
- package/dist/filters/reflection-gpu.d.ts +3 -1
- package/dist/filters/reflection-gpu.js +5 -2
- package/dist/filters/reflection-gpu.js.map +2 -2
- package/dist/filters/render-backdrop-contrast-boundary.d.ts +31 -0
- package/dist/filters/render-backdrop-contrast-boundary.js +116 -0
- package/dist/filters/render-backdrop-contrast-boundary.js.map +7 -0
- package/dist/filters/render-emboss-boundary.d.ts +13 -0
- package/dist/filters/render-emboss-boundary.js +131 -0
- package/dist/filters/render-emboss-boundary.js.map +7 -0
- package/dist/filters.d.ts +9 -5
- package/dist/filters.js +4 -0
- package/dist/filters.js.map +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +2 -2
- package/dist/internal.d.ts +2 -0
- package/dist/internal.js +4 -0
- package/dist/internal.js.map +2 -2
- package/dist/lib/events/event-facade.d.ts +13 -0
- package/dist/lib/events/event-facade.js +23 -0
- package/dist/lib/events/event-facade.js.map +2 -2
- package/dist/lib/events/propagation.js +19 -14
- package/dist/lib/events/propagation.js.map +2 -2
- package/dist/lib/execute-render.js +13 -0
- package/dist/lib/execute-render.js.map +2 -2
- package/dist/lib/recording/recording.d.ts +43 -0
- package/dist/lib/recording/recording.js +555 -0
- package/dist/lib/recording/recording.js.map +7 -0
- package/dist/lib/recording/types.d.ts +118 -0
- package/dist/lib/recording/wasm-bytes.d.ts +1 -0
- package/dist/lib/recording/wasm-bytes.js +5 -0
- package/dist/lib/recording/wasm-bytes.js.map +7 -0
- package/dist/lib/recording/worker-source.d.ts +1 -0
- package/dist/lib/recording/worker-source.js +5 -0
- package/dist/lib/recording/worker-source.js.map +7 -0
- package/dist/lib/render-transaction.d.ts +5 -2
- package/dist/lib/render-transaction.js +23 -1
- package/dist/lib/render-transaction.js.map +2 -2
- package/dist/lib/series-inspection-frame.d.ts +18 -0
- package/dist/lib/series-inspection-frame.js +70 -0
- package/dist/lib/series-inspection-frame.js.map +7 -0
- package/dist/lib/types.d.ts +6 -0
- package/package.json +10 -2
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineTexture
|
|
3
|
+
} from "@pibbl/core";
|
|
4
|
+
import { paletteLut, texturePalettes, validateSeed } from "./palette.js";
|
|
5
|
+
import {
|
|
6
|
+
ChemicalField,
|
|
7
|
+
schnakenbergModel,
|
|
8
|
+
barkleyModel,
|
|
9
|
+
brusselatorModel
|
|
10
|
+
} from "./chemical-field.js";
|
|
11
|
+
const schnakenbergPresets = Object.freeze({
|
|
12
|
+
/** Separated activator spots. See {@link schnakenberg}. */
|
|
13
|
+
spots: Object.freeze({ a: 0.1, b: 0.9, diffusionU: 1, diffusionV: 20 }),
|
|
14
|
+
/** Connected activator bands. See {@link schnakenberg}. */
|
|
15
|
+
labyrinths: Object.freeze({
|
|
16
|
+
a: 0.01,
|
|
17
|
+
b: 1.7,
|
|
18
|
+
diffusionU: 1,
|
|
19
|
+
diffusionV: 20,
|
|
20
|
+
warmupSteps: 1e4
|
|
21
|
+
})
|
|
22
|
+
});
|
|
23
|
+
const barkleyPresets = Object.freeze({
|
|
24
|
+
/** Broken excitation fronts form rotating spirals. See {@link barkley}. */
|
|
25
|
+
spirals: Object.freeze({
|
|
26
|
+
a: 0.75,
|
|
27
|
+
b: 0.02,
|
|
28
|
+
epsilon: 0.02,
|
|
29
|
+
diffusionU: 1,
|
|
30
|
+
diffusionV: 0
|
|
31
|
+
}),
|
|
32
|
+
/** Broader propagating excitation fronts. See {@link barkley}. */
|
|
33
|
+
waves: Object.freeze({
|
|
34
|
+
a: 0.9,
|
|
35
|
+
b: 0.01,
|
|
36
|
+
epsilon: 0.04,
|
|
37
|
+
diffusionU: 1,
|
|
38
|
+
diffusionV: 0
|
|
39
|
+
})
|
|
40
|
+
});
|
|
41
|
+
const brusselatorPresets = Object.freeze({
|
|
42
|
+
/** Differential diffusion supports stationary spots. See {@link brusselator}. */
|
|
43
|
+
spots: Object.freeze({
|
|
44
|
+
a: 1,
|
|
45
|
+
b: 1.9,
|
|
46
|
+
diffusionU: 0.2,
|
|
47
|
+
diffusionV: 2,
|
|
48
|
+
warmupSteps: 1e4
|
|
49
|
+
}),
|
|
50
|
+
/** Equal diffusion above the oscillation threshold. See {@link brusselator}. */
|
|
51
|
+
oscillations: Object.freeze({ a: 1, b: 3, diffusionU: 0.3, diffusionV: 0.3 })
|
|
52
|
+
});
|
|
53
|
+
function bounded(name, value, min, max, integer = false) {
|
|
54
|
+
if (!Number.isFinite(value) || value < min || value > max || integer && !Number.isInteger(value))
|
|
55
|
+
throw new RangeError(
|
|
56
|
+
`${name} must be ${integer ? "an integer " : ""}within ${min}..${max}.`
|
|
57
|
+
);
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
function common(options) {
|
|
61
|
+
if (options.paused !== void 0 && typeof options.paused !== "boolean")
|
|
62
|
+
throw new TypeError("Chemical paused must be boolean.");
|
|
63
|
+
return {
|
|
64
|
+
seed: validateSeed(options.seed),
|
|
65
|
+
initialNoise: bounded(
|
|
66
|
+
"Chemical initialNoise",
|
|
67
|
+
options.initialNoise ?? 0.1,
|
|
68
|
+
0,
|
|
69
|
+
1
|
|
70
|
+
),
|
|
71
|
+
warmupSteps: bounded(
|
|
72
|
+
"Chemical warmupSteps",
|
|
73
|
+
options.warmupSteps ?? 4096,
|
|
74
|
+
0,
|
|
75
|
+
12e3,
|
|
76
|
+
true
|
|
77
|
+
),
|
|
78
|
+
speed: bounded("Chemical speed", options.speed ?? 1, 0, 4),
|
|
79
|
+
paused: options.paused ?? false
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function diffusion(options, defaults) {
|
|
83
|
+
return {
|
|
84
|
+
diffusionU: bounded(
|
|
85
|
+
"Chemical diffusionU",
|
|
86
|
+
options.diffusionU ?? defaults.diffusionU,
|
|
87
|
+
0,
|
|
88
|
+
32
|
|
89
|
+
),
|
|
90
|
+
diffusionV: bounded(
|
|
91
|
+
"Chemical diffusionV",
|
|
92
|
+
options.diffusionV ?? defaults.diffusionV,
|
|
93
|
+
0,
|
|
94
|
+
32
|
|
95
|
+
)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function schnakenbergConfig(options) {
|
|
99
|
+
return {
|
|
100
|
+
...common(options),
|
|
101
|
+
...diffusion(options, schnakenbergPresets.spots),
|
|
102
|
+
a: bounded("Schnakenberg a", options.a ?? 0.1, 0.01, 2),
|
|
103
|
+
b: bounded("Schnakenberg b", options.b ?? 0.9, 0.01, 2),
|
|
104
|
+
epsilon: 0.02
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function barkleyConfig(options) {
|
|
108
|
+
return {
|
|
109
|
+
...common(options),
|
|
110
|
+
...diffusion(options, barkleyPresets.spirals),
|
|
111
|
+
a: bounded("Barkley a", options.a ?? 0.75, 0.3, 1.2),
|
|
112
|
+
b: bounded("Barkley b", options.b ?? 0.02, 0, 0.2),
|
|
113
|
+
epsilon: bounded("Barkley epsilon", options.epsilon ?? 0.02, 5e-3, 0.1)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function brusselatorConfig(options) {
|
|
117
|
+
return {
|
|
118
|
+
...common(options),
|
|
119
|
+
...diffusion(options, brusselatorPresets.spots),
|
|
120
|
+
a: bounded("Brusselator a", options.a ?? 1, 0.1, 3),
|
|
121
|
+
b: bounded("Brusselator b", options.b ?? 1.8, 0.1, 5),
|
|
122
|
+
epsilon: 0.02
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function chemicalRecipe(model) {
|
|
126
|
+
const makeField = (context, config) => {
|
|
127
|
+
if (context.canvas.width < 3 || context.canvas.height < 3)
|
|
128
|
+
throw new RangeError(
|
|
129
|
+
"Chemical textures require at least 3\xD73 raster samples."
|
|
130
|
+
);
|
|
131
|
+
return new ChemicalField({
|
|
132
|
+
width: context.canvas.width - 1,
|
|
133
|
+
height: context.canvas.height - 1,
|
|
134
|
+
config,
|
|
135
|
+
model
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
const active = (state) => !state.paused && state.config.speed > 0;
|
|
139
|
+
const reset = (state, context) => {
|
|
140
|
+
const next = makeField(context, state.config);
|
|
141
|
+
state.field.dispose();
|
|
142
|
+
state.field = next;
|
|
143
|
+
state.elapsed = 0;
|
|
144
|
+
state.fresh = true;
|
|
145
|
+
context.invalidate();
|
|
146
|
+
if (active(state)) context.requestFrame();
|
|
147
|
+
};
|
|
148
|
+
return defineTexture({
|
|
149
|
+
defaultPlacement: { mode: "repeat" },
|
|
150
|
+
create(context, config) {
|
|
151
|
+
const state = {
|
|
152
|
+
config,
|
|
153
|
+
field: makeField(context, config),
|
|
154
|
+
paused: config.paused,
|
|
155
|
+
elapsed: 0,
|
|
156
|
+
fresh: true,
|
|
157
|
+
image: new ImageData(context.canvas.width, context.canvas.height),
|
|
158
|
+
lut: void 0,
|
|
159
|
+
paletteKey: ""
|
|
160
|
+
};
|
|
161
|
+
if (active(state)) context.requestFrame();
|
|
162
|
+
return state;
|
|
163
|
+
},
|
|
164
|
+
update(state, config, context) {
|
|
165
|
+
if (JSON.stringify(config) === JSON.stringify(state.config)) return;
|
|
166
|
+
const { speed: _speed, paused: _paused, ...previous } = state.config;
|
|
167
|
+
const { speed, paused, ...next } = config;
|
|
168
|
+
const changed = JSON.stringify(previous) !== JSON.stringify(next);
|
|
169
|
+
if (paused !== state.config.paused) state.paused = paused;
|
|
170
|
+
state.config = config;
|
|
171
|
+
state.elapsed = 0;
|
|
172
|
+
state.fresh = true;
|
|
173
|
+
if (changed) reset(state, context);
|
|
174
|
+
if (!state.paused && speed > 0) context.requestFrame();
|
|
175
|
+
},
|
|
176
|
+
receive(state, message, context) {
|
|
177
|
+
if (message.type === "pause") {
|
|
178
|
+
if (typeof message.paused !== "boolean")
|
|
179
|
+
throw new TypeError("Chemical pause requires a boolean.");
|
|
180
|
+
state.paused = message.paused;
|
|
181
|
+
state.elapsed = 0;
|
|
182
|
+
state.fresh = true;
|
|
183
|
+
if (active(state)) context.requestFrame();
|
|
184
|
+
} else if (message.type === "reset") reset(state, context);
|
|
185
|
+
else if (message.type === "paint" || message.type === "stir") {
|
|
186
|
+
const radius = bounded(
|
|
187
|
+
"Chemical brush radius",
|
|
188
|
+
message.radius ?? (message.type === "paint" ? 6 : 16),
|
|
189
|
+
0.01,
|
|
190
|
+
128
|
|
191
|
+
);
|
|
192
|
+
if (!Number.isFinite(message.u) || !Number.isFinite(message.v))
|
|
193
|
+
throw new RangeError("Chemical brush coordinates must be finite.");
|
|
194
|
+
if (message.type === "paint") {
|
|
195
|
+
const strength = bounded(
|
|
196
|
+
"Chemical brush strength",
|
|
197
|
+
message.strength ?? 0.8,
|
|
198
|
+
0,
|
|
199
|
+
1
|
|
200
|
+
);
|
|
201
|
+
if (message.u < 0 || message.u > 1 || message.v < 0 || message.v > 1)
|
|
202
|
+
return;
|
|
203
|
+
if (strength === 0) return;
|
|
204
|
+
state.field.paint({ ...message, radius, strength });
|
|
205
|
+
} else {
|
|
206
|
+
const du = bounded("Chemical stir du", message.du, -1, 1), dv = bounded("Chemical stir dv", message.dv, -1, 1);
|
|
207
|
+
if (message.u < 0 || message.u > 1 || message.v < 0 || message.v > 1)
|
|
208
|
+
return;
|
|
209
|
+
state.field.stir({ ...message, radius, du, dv });
|
|
210
|
+
}
|
|
211
|
+
context.invalidate();
|
|
212
|
+
} else throw new TypeError("Unknown chemical texture message.");
|
|
213
|
+
},
|
|
214
|
+
advance(state, frame, context) {
|
|
215
|
+
if (!active(state)) return;
|
|
216
|
+
if (!state.fresh) {
|
|
217
|
+
state.elapsed += Math.min(50, frame.delta) * state.config.speed * 0.48;
|
|
218
|
+
const count = Math.min(96, Math.floor(state.elapsed));
|
|
219
|
+
state.elapsed -= count;
|
|
220
|
+
if (count > 0) {
|
|
221
|
+
state.field.advance(count);
|
|
222
|
+
context.invalidate();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
state.fresh = false;
|
|
226
|
+
context.requestFrame();
|
|
227
|
+
},
|
|
228
|
+
rasterize(state, context) {
|
|
229
|
+
const key = (context.palette ?? texturePalettes.lagoon).join();
|
|
230
|
+
if (key !== state.paletteKey) {
|
|
231
|
+
state.lut = paletteLut(context.palette ?? texturePalettes.lagoon);
|
|
232
|
+
state.paletteKey = key;
|
|
233
|
+
}
|
|
234
|
+
const { width, height } = context.canvas, data = state.image.data, lut = state.lut;
|
|
235
|
+
for (let y = 0; y < height; y++)
|
|
236
|
+
for (let x = 0; x < width; x++) {
|
|
237
|
+
const index = y % state.field.height * state.field.width + x % state.field.width;
|
|
238
|
+
const color = Math.round(
|
|
239
|
+
Math.max(0, Math.min(1, state.field.intensity(index))) * 255
|
|
240
|
+
) * 4, i = (y * width + x) * 4;
|
|
241
|
+
data[i] = lut[color];
|
|
242
|
+
data[i + 1] = lut[color + 1];
|
|
243
|
+
data[i + 2] = lut[color + 2];
|
|
244
|
+
data[i + 3] = 255;
|
|
245
|
+
}
|
|
246
|
+
context.canvas.getContext("2d").putImageData(state.image, 0, 0);
|
|
247
|
+
},
|
|
248
|
+
dispose(state) {
|
|
249
|
+
state.field.dispose();
|
|
250
|
+
state.image = void 0;
|
|
251
|
+
state.lut = void 0;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const schnakenbergRecipe = /* @__PURE__ */ chemicalRecipe(schnakenbergModel);
|
|
256
|
+
const barkleyRecipe = /* @__PURE__ */ chemicalRecipe(barkleyModel);
|
|
257
|
+
const brusselatorRecipe = /* @__PURE__ */ chemicalRecipe(brusselatorModel);
|
|
258
|
+
function schnakenberg(options = {}) {
|
|
259
|
+
return schnakenbergRecipe(schnakenbergConfig(options));
|
|
260
|
+
}
|
|
261
|
+
function barkley(options = {}) {
|
|
262
|
+
return barkleyRecipe(barkleyConfig(options));
|
|
263
|
+
}
|
|
264
|
+
function brusselator(options = {}) {
|
|
265
|
+
return brusselatorRecipe(brusselatorConfig(options));
|
|
266
|
+
}
|
|
267
|
+
export {
|
|
268
|
+
barkley,
|
|
269
|
+
barkleyPresets,
|
|
270
|
+
brusselator,
|
|
271
|
+
brusselatorPresets,
|
|
272
|
+
schnakenberg,
|
|
273
|
+
schnakenbergPresets
|
|
274
|
+
};
|
|
275
|
+
//# sourceMappingURL=chemical-recipes.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/features/textures/lib/chemical-recipes.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n defineTexture,\n type TextureContext,\n type TextureRecipe,\n} from \"@pibbl/core\";\nimport type { InkMessage } from \"./definitions.js\";\nimport { paletteLut, texturePalettes, validateSeed } from \"./palette.js\";\nimport {\n ChemicalField,\n schnakenbergModel,\n barkleyModel,\n brusselatorModel,\n type ChemicalConfig,\n} from \"./chemical-field.js\";\n\n/** Shared simulation timing, diffusion and initialization controls. See {@link SchnakenbergOptions}. */\ninterface ChemicalOptions {\n /** Unsigned 32-bit initialization seed; default 42. See {@link schnakenberg}. */\n readonly seed?: number;\n /** Activator diffusion per grid cell, finite 0\u201332. See {@link schnakenberg}. */\n readonly diffusionU?: number;\n /** Inhibitor diffusion per grid cell, finite 0\u201332. See {@link schnakenberg}. */\n readonly diffusionV?: number;\n /** Initial seeded disturbance amplitude, finite 0\u20131; default 0.1. See {@link schnakenberg}. */\n readonly initialNoise?: number;\n /** Initialization steps, integer 0\u201312000; default 4096. See {@link schnakenberg}. */\n readonly warmupSteps?: number;\n /** Multiplier of 480 numerical steps/second, finite 0\u20134; default 1. Zero idles. See {@link schnakenberg}. */\n readonly speed?: number;\n /** Initially suspend stepping; default false. See {@link InkMessage}. */\n readonly paused?: boolean;\n}\n/** Schnakenberg production rates, diffusion and initialization. See {@link schnakenberg}. */\nexport interface SchnakenbergOptions extends ChemicalOptions {\n /** Activator source, finite 0.01\u20132; default 0.1. See {@link schnakenberg}. */\n readonly a?: number;\n /** Inhibitor source, finite 0.01\u20132; default 0.9. See {@link schnakenberg}. */\n readonly b?: number;\n}\n/** Excitability, recovery, diffusion and initialization. See {@link barkley}. */\nexport interface BarkleyOptions extends ChemicalOptions {\n /** Excitability scale, finite 0.3\u20131.2; default 0.75. See {@link barkley}. */\n readonly a?: number;\n /** Excitation threshold offset, finite 0\u20130.2; default 0.02. See {@link barkley}. */\n readonly b?: number;\n /** Fast/slow time separation, finite 0.005\u20130.1; default 0.02. See {@link barkley}. */\n readonly epsilon?: number;\n}\n/** Brusselator feed rates, diffusion and initialization. See {@link brusselator}. */\nexport interface BrusselatorOptions extends ChemicalOptions {\n /** Activator feed, finite 0.1\u20133; default 1. See {@link brusselator}. */\n readonly a?: number;\n /** Conversion rate, finite 0.1\u20135; default 1.8. See {@link brusselator}. */\n readonly b?: number;\n}\n/** Immutable Schnakenberg starting configurations. See {@link SchnakenbergOptions}. */\nexport const schnakenbergPresets = Object.freeze({\n /** Separated activator spots. See {@link schnakenberg}. */\n spots: Object.freeze({ a: 0.1, b: 0.9, diffusionU: 1, diffusionV: 20 }),\n /** Connected activator bands. See {@link schnakenberg}. */\n labyrinths: Object.freeze({\n a: 0.01,\n b: 1.7,\n diffusionU: 1,\n diffusionV: 20,\n warmupSteps: 10000,\n }),\n});\n/** Immutable Barkley starting configurations. See {@link BarkleyOptions}. */\nexport const barkleyPresets = Object.freeze({\n /** Broken excitation fronts form rotating spirals. See {@link barkley}. */\n spirals: Object.freeze({\n a: 0.75,\n b: 0.02,\n epsilon: 0.02,\n diffusionU: 1,\n diffusionV: 0,\n }),\n /** Broader propagating excitation fronts. See {@link barkley}. */\n waves: Object.freeze({\n a: 0.9,\n b: 0.01,\n epsilon: 0.04,\n diffusionU: 1,\n diffusionV: 0,\n }),\n});\n/** Immutable Brusselator starting configurations. See {@link BrusselatorOptions}. */\nexport const brusselatorPresets = Object.freeze({\n /** Differential diffusion supports stationary spots. See {@link brusselator}. */\n spots: Object.freeze({\n a: 1,\n b: 1.9,\n diffusionU: 0.2,\n diffusionV: 2,\n warmupSteps: 10000,\n }),\n /** Equal diffusion above the oscillation threshold. See {@link brusselator}. */\n oscillations: Object.freeze({ a: 1, b: 3, diffusionU: 0.3, diffusionV: 0.3 }),\n});\nfunction bounded(\n name: string,\n value: number,\n min: number,\n max: number,\n integer = false,\n) {\n if (\n !Number.isFinite(value) ||\n value < min ||\n value > max ||\n (integer && !Number.isInteger(value))\n )\n throw new RangeError(\n `${name} must be ${integer ? \"an integer \" : \"\"}within ${min}..${max}.`,\n );\n return value;\n}\nfunction common(\n options: ChemicalOptions,\n): Omit<ChemicalConfig, \"a\" | \"b\" | \"epsilon\" | \"diffusionU\" | \"diffusionV\"> {\n if (options.paused !== undefined && typeof options.paused !== \"boolean\")\n throw new TypeError(\"Chemical paused must be boolean.\");\n return {\n seed: validateSeed(options.seed),\n initialNoise: bounded(\n \"Chemical initialNoise\",\n options.initialNoise ?? 0.1,\n 0,\n 1,\n ),\n warmupSteps: bounded(\n \"Chemical warmupSteps\",\n options.warmupSteps ?? 4096,\n 0,\n 12000,\n true,\n ),\n speed: bounded(\"Chemical speed\", options.speed ?? 1, 0, 4),\n paused: options.paused ?? false,\n };\n}\nfunction diffusion(\n options: ChemicalOptions,\n defaults: { diffusionU: number; diffusionV: number },\n) {\n return {\n diffusionU: bounded(\n \"Chemical diffusionU\",\n options.diffusionU ?? defaults.diffusionU,\n 0,\n 32,\n ),\n diffusionV: bounded(\n \"Chemical diffusionV\",\n options.diffusionV ?? defaults.diffusionV,\n 0,\n 32,\n ),\n };\n}\nfunction schnakenbergConfig(options: SchnakenbergOptions): ChemicalConfig {\n return {\n ...common(options),\n ...diffusion(options, schnakenbergPresets.spots),\n a: bounded(\"Schnakenberg a\", options.a ?? 0.1, 0.01, 2),\n b: bounded(\"Schnakenberg b\", options.b ?? 0.9, 0.01, 2),\n epsilon: 0.02,\n };\n}\nfunction barkleyConfig(options: BarkleyOptions): ChemicalConfig {\n return {\n ...common(options),\n ...diffusion(options, barkleyPresets.spirals),\n a: bounded(\"Barkley a\", options.a ?? 0.75, 0.3, 1.2),\n b: bounded(\"Barkley b\", options.b ?? 0.02, 0, 0.2),\n epsilon: bounded(\"Barkley epsilon\", options.epsilon ?? 0.02, 0.005, 0.1),\n };\n}\nfunction brusselatorConfig(options: BrusselatorOptions): ChemicalConfig {\n return {\n ...common(options),\n ...diffusion(options, brusselatorPresets.spots),\n a: bounded(\"Brusselator a\", options.a ?? 1, 0.1, 3),\n b: bounded(\"Brusselator b\", options.b ?? 1.8, 0.1, 5),\n epsilon: 0.02,\n };\n}\ninterface State {\n config: ChemicalConfig;\n field: ChemicalField;\n paused: boolean;\n elapsed: number;\n fresh: boolean;\n image: ImageData | undefined;\n lut: Uint8ClampedArray | undefined;\n paletteKey: string;\n}\nfunction chemicalRecipe(model: typeof schnakenbergModel) {\n const makeField = (context: TextureContext, config: ChemicalConfig) => {\n if (context.canvas.width < 3 || context.canvas.height < 3)\n throw new RangeError(\n \"Chemical textures require at least 3\u00D73 raster samples.\",\n );\n return new ChemicalField({\n width: context.canvas.width - 1,\n height: context.canvas.height - 1,\n config,\n model,\n });\n };\n const active = (state: State) => !state.paused && state.config.speed > 0;\n const reset = (state: State, context: TextureContext) => {\n const next = makeField(context, state.config);\n state.field.dispose();\n state.field = next;\n state.elapsed = 0;\n state.fresh = true;\n context.invalidate();\n if (active(state)) context.requestFrame();\n };\n return defineTexture<ChemicalConfig, State, InkMessage>({\n defaultPlacement: { mode: \"repeat\" },\n create(context, config) {\n const state: State = {\n config,\n field: makeField(context, config),\n paused: config.paused,\n elapsed: 0,\n fresh: true,\n image: new ImageData(context.canvas.width, context.canvas.height),\n lut: undefined,\n paletteKey: \"\",\n };\n if (active(state)) context.requestFrame();\n return state;\n },\n update(state, config, context) {\n if (JSON.stringify(config) === JSON.stringify(state.config)) return;\n const { speed: _speed, paused: _paused, ...previous } = state.config;\n const { speed, paused, ...next } = config;\n const changed = JSON.stringify(previous) !== JSON.stringify(next);\n if (paused !== state.config.paused) state.paused = paused;\n state.config = config;\n state.elapsed = 0;\n state.fresh = true;\n if (changed) reset(state, context);\n if (!state.paused && speed > 0) context.requestFrame();\n },\n receive(state, message, context) {\n if (message.type === \"pause\") {\n if (typeof message.paused !== \"boolean\")\n throw new TypeError(\"Chemical pause requires a boolean.\");\n state.paused = message.paused;\n state.elapsed = 0;\n state.fresh = true;\n if (active(state)) context.requestFrame();\n } else if (message.type === \"reset\") reset(state, context);\n else if (message.type === \"paint\" || message.type === \"stir\") {\n const radius = bounded(\n \"Chemical brush radius\",\n message.radius ?? (message.type === \"paint\" ? 6 : 16),\n 0.01,\n 128,\n );\n if (!Number.isFinite(message.u) || !Number.isFinite(message.v))\n throw new RangeError(\"Chemical brush coordinates must be finite.\");\n if (message.type === \"paint\") {\n const strength = bounded(\n \"Chemical brush strength\",\n message.strength ?? 0.8,\n 0,\n 1,\n );\n if (message.u < 0 || message.u > 1 || message.v < 0 || message.v > 1)\n return;\n if (strength === 0) return;\n state.field.paint({ ...message, radius, strength });\n } else {\n const du = bounded(\"Chemical stir du\", message.du, -1, 1),\n dv = bounded(\"Chemical stir dv\", message.dv, -1, 1);\n if (message.u < 0 || message.u > 1 || message.v < 0 || message.v > 1)\n return;\n state.field.stir({ ...message, radius, du, dv });\n }\n context.invalidate();\n } else throw new TypeError(\"Unknown chemical texture message.\");\n },\n advance(state, frame, context) {\n if (!active(state)) return;\n if (!state.fresh) {\n state.elapsed += Math.min(50, frame.delta) * state.config.speed * 0.48;\n const count = Math.min(96, Math.floor(state.elapsed));\n state.elapsed -= count;\n if (count > 0) {\n state.field.advance(count);\n context.invalidate();\n }\n }\n state.fresh = false;\n context.requestFrame();\n },\n rasterize(state, context) {\n const key = (context.palette ?? texturePalettes.lagoon).join();\n if (key !== state.paletteKey) {\n state.lut = paletteLut(context.palette ?? texturePalettes.lagoon);\n state.paletteKey = key;\n }\n const { width, height } = context.canvas,\n data = state.image!.data,\n lut = state.lut!;\n for (let y = 0; y < height; y++)\n for (let x = 0; x < width; x++) {\n const index =\n (y % state.field.height) * state.field.width +\n (x % state.field.width);\n const color =\n Math.round(\n Math.max(0, Math.min(1, state.field.intensity(index))) * 255,\n ) * 4,\n i = (y * width + x) * 4;\n data[i] = lut[color]!;\n data[i + 1] = lut[color + 1]!;\n data[i + 2] = lut[color + 2]!;\n data[i + 3] = 255;\n }\n context.canvas.getContext(\"2d\")!.putImageData(state.image!, 0, 0);\n },\n dispose(state) {\n state.field.dispose();\n state.image = undefined;\n state.lut = undefined;\n },\n });\n}\nconst schnakenbergRecipe = /* @__PURE__ */ chemicalRecipe(schnakenbergModel);\nconst barkleyRecipe = /* @__PURE__ */ chemicalRecipe(barkleyModel);\nconst brusselatorRecipe = /* @__PURE__ */ chemicalRecipe(brusselatorModel);\n/**\n * Creates a periodic Schnakenberg activator/inhibitor texture with paint, stir, pause and reset.\n * @param options - Reaction rates, diffusion and initialization. See {@link SchnakenbergOptions}.\n * @returns A mountable simulation recipe. See {@link TextureRecipe}, {@link InkMessage}.\n * @see {@link schnakenbergPresets}\n */\nexport function schnakenberg(\n options: SchnakenbergOptions = {},\n): TextureRecipe<InkMessage> {\n return schnakenbergRecipe(schnakenbergConfig(options));\n}\n/**\n * Creates a periodic Barkley excitable texture initialized with a broken excitation front.\n * @param options - Excitability, recovery, diffusion and initialization. See {@link BarkleyOptions}.\n * @returns A mountable simulation recipe. See {@link TextureRecipe}, {@link InkMessage}.\n * @see {@link barkleyPresets}\n */\nexport function barkley(\n options: BarkleyOptions = {},\n): TextureRecipe<InkMessage> {\n return barkleyRecipe(barkleyConfig(options));\n}\n/**\n * Creates a periodic Brusselator texture with paint, stir, pause and reset.\n * @param options - Feed rates, diffusion and initialization. See {@link BrusselatorOptions}.\n * @returns A mountable simulation recipe. See {@link TextureRecipe}, {@link InkMessage}.\n * @see {@link brusselatorPresets}\n */\nexport function brusselator(\n options: BrusselatorOptions = {},\n): TextureRecipe<InkMessage> {\n return brusselatorRecipe(brusselatorConfig(options));\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,OAGK;AAEP,SAAS,YAAY,iBAAiB,oBAAoB;AAC1D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA2CA,MAAM,sBAAsB,OAAO,OAAO;AAAA;AAAA,EAE/C,OAAO,OAAO,OAAO,EAAE,GAAG,KAAK,GAAG,KAAK,YAAY,GAAG,YAAY,GAAG,CAAC;AAAA;AAAA,EAEtE,YAAY,OAAO,OAAO;AAAA,IACxB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AACH,CAAC;AAEM,MAAM,iBAAiB,OAAO,OAAO;AAAA;AAAA,EAE1C,SAAS,OAAO,OAAO;AAAA,IACrB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,YAAY;AAAA,EACd,CAAC;AAAA;AAAA,EAED,OAAO,OAAO,OAAO;AAAA,IACnB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,YAAY;AAAA,EACd,CAAC;AACH,CAAC;AAEM,MAAM,qBAAqB,OAAO,OAAO;AAAA;AAAA,EAE9C,OAAO,OAAO,OAAO;AAAA,IACnB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA;AAAA,EAED,cAAc,OAAO,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,YAAY,KAAK,YAAY,IAAI,CAAC;AAC9E,CAAC;AACD,SAAS,QACP,MACA,OACA,KACA,KACA,UAAU,OACV;AACA,MACE,CAAC,OAAO,SAAS,KAAK,KACtB,QAAQ,OACR,QAAQ,OACP,WAAW,CAAC,OAAO,UAAU,KAAK;AAEnC,UAAM,IAAI;AAAA,MACR,GAAG,IAAI,YAAY,UAAU,gBAAgB,EAAE,UAAU,GAAG,KAAK,GAAG;AAAA,IACtE;AACF,SAAO;AACT;AACA,SAAS,OACP,SAC2E;AAC3E,MAAI,QAAQ,WAAW,UAAa,OAAO,QAAQ,WAAW;AAC5D,UAAM,IAAI,UAAU,kCAAkC;AACxD,SAAO;AAAA,IACL,MAAM,aAAa,QAAQ,IAAI;AAAA,IAC/B,cAAc;AAAA,MACZ;AAAA,MACA,QAAQ,gBAAgB;AAAA,MACxB;AAAA,MACA;AAAA,IACF;AAAA,IACA,aAAa;AAAA,MACX;AAAA,MACA,QAAQ,eAAe;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,OAAO,QAAQ,kBAAkB,QAAQ,SAAS,GAAG,GAAG,CAAC;AAAA,IACzD,QAAQ,QAAQ,UAAU;AAAA,EAC5B;AACF;AACA,SAAS,UACP,SACA,UACA;AACA,SAAO;AAAA,IACL,YAAY;AAAA,MACV;AAAA,MACA,QAAQ,cAAc,SAAS;AAAA,MAC/B;AAAA,MACA;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV;AAAA,MACA,QAAQ,cAAc,SAAS;AAAA,MAC/B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AACA,SAAS,mBAAmB,SAA8C;AACxE,SAAO;AAAA,IACL,GAAG,OAAO,OAAO;AAAA,IACjB,GAAG,UAAU,SAAS,oBAAoB,KAAK;AAAA,IAC/C,GAAG,QAAQ,kBAAkB,QAAQ,KAAK,KAAK,MAAM,CAAC;AAAA,IACtD,GAAG,QAAQ,kBAAkB,QAAQ,KAAK,KAAK,MAAM,CAAC;AAAA,IACtD,SAAS;AAAA,EACX;AACF;AACA,SAAS,cAAc,SAAyC;AAC9D,SAAO;AAAA,IACL,GAAG,OAAO,OAAO;AAAA,IACjB,GAAG,UAAU,SAAS,eAAe,OAAO;AAAA,IAC5C,GAAG,QAAQ,aAAa,QAAQ,KAAK,MAAM,KAAK,GAAG;AAAA,IACnD,GAAG,QAAQ,aAAa,QAAQ,KAAK,MAAM,GAAG,GAAG;AAAA,IACjD,SAAS,QAAQ,mBAAmB,QAAQ,WAAW,MAAM,MAAO,GAAG;AAAA,EACzE;AACF;AACA,SAAS,kBAAkB,SAA6C;AACtE,SAAO;AAAA,IACL,GAAG,OAAO,OAAO;AAAA,IACjB,GAAG,UAAU,SAAS,mBAAmB,KAAK;AAAA,IAC9C,GAAG,QAAQ,iBAAiB,QAAQ,KAAK,GAAG,KAAK,CAAC;AAAA,IAClD,GAAG,QAAQ,iBAAiB,QAAQ,KAAK,KAAK,KAAK,CAAC;AAAA,IACpD,SAAS;AAAA,EACX;AACF;AAWA,SAAS,eAAe,OAAiC;AACvD,QAAM,YAAY,CAAC,SAAyB,WAA2B;AACrE,QAAI,QAAQ,OAAO,QAAQ,KAAK,QAAQ,OAAO,SAAS;AACtD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AACF,WAAO,IAAI,cAAc;AAAA,MACvB,OAAO,QAAQ,OAAO,QAAQ;AAAA,MAC9B,QAAQ,QAAQ,OAAO,SAAS;AAAA,MAChC;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,SAAS,CAAC,UAAiB,CAAC,MAAM,UAAU,MAAM,OAAO,QAAQ;AACvE,QAAM,QAAQ,CAAC,OAAc,YAA4B;AACvD,UAAM,OAAO,UAAU,SAAS,MAAM,MAAM;AAC5C,UAAM,MAAM,QAAQ;AACpB,UAAM,QAAQ;AACd,UAAM,UAAU;AAChB,UAAM,QAAQ;AACd,YAAQ,WAAW;AACnB,QAAI,OAAO,KAAK,EAAG,SAAQ,aAAa;AAAA,EAC1C;AACA,SAAO,cAAiD;AAAA,IACtD,kBAAkB,EAAE,MAAM,SAAS;AAAA,IACnC,OAAO,SAAS,QAAQ;AACtB,YAAM,QAAe;AAAA,QACnB;AAAA,QACA,OAAO,UAAU,SAAS,MAAM;AAAA,QAChC,QAAQ,OAAO;AAAA,QACf,SAAS;AAAA,QACT,OAAO;AAAA,QACP,OAAO,IAAI,UAAU,QAAQ,OAAO,OAAO,QAAQ,OAAO,MAAM;AAAA,QAChE,KAAK;AAAA,QACL,YAAY;AAAA,MACd;AACA,UAAI,OAAO,KAAK,EAAG,SAAQ,aAAa;AACxC,aAAO;AAAA,IACT;AAAA,IACA,OAAO,OAAO,QAAQ,SAAS;AAC7B,UAAI,KAAK,UAAU,MAAM,MAAM,KAAK,UAAU,MAAM,MAAM,EAAG;AAC7D,YAAM,EAAE,OAAO,QAAQ,QAAQ,SAAS,GAAG,SAAS,IAAI,MAAM;AAC9D,YAAM,EAAE,OAAO,QAAQ,GAAG,KAAK,IAAI;AACnC,YAAM,UAAU,KAAK,UAAU,QAAQ,MAAM,KAAK,UAAU,IAAI;AAChE,UAAI,WAAW,MAAM,OAAO,OAAQ,OAAM,SAAS;AACnD,YAAM,SAAS;AACf,YAAM,UAAU;AAChB,YAAM,QAAQ;AACd,UAAI,QAAS,OAAM,OAAO,OAAO;AACjC,UAAI,CAAC,MAAM,UAAU,QAAQ,EAAG,SAAQ,aAAa;AAAA,IACvD;AAAA,IACA,QAAQ,OAAO,SAAS,SAAS;AAC/B,UAAI,QAAQ,SAAS,SAAS;AAC5B,YAAI,OAAO,QAAQ,WAAW;AAC5B,gBAAM,IAAI,UAAU,oCAAoC;AAC1D,cAAM,SAAS,QAAQ;AACvB,cAAM,UAAU;AAChB,cAAM,QAAQ;AACd,YAAI,OAAO,KAAK,EAAG,SAAQ,aAAa;AAAA,MAC1C,WAAW,QAAQ,SAAS,QAAS,OAAM,OAAO,OAAO;AAAA,eAChD,QAAQ,SAAS,WAAW,QAAQ,SAAS,QAAQ;AAC5D,cAAM,SAAS;AAAA,UACb;AAAA,UACA,QAAQ,WAAW,QAAQ,SAAS,UAAU,IAAI;AAAA,UAClD;AAAA,UACA;AAAA,QACF;AACA,YAAI,CAAC,OAAO,SAAS,QAAQ,CAAC,KAAK,CAAC,OAAO,SAAS,QAAQ,CAAC;AAC3D,gBAAM,IAAI,WAAW,4CAA4C;AACnE,YAAI,QAAQ,SAAS,SAAS;AAC5B,gBAAM,WAAW;AAAA,YACf;AAAA,YACA,QAAQ,YAAY;AAAA,YACpB;AAAA,YACA;AAAA,UACF;AACA,cAAI,QAAQ,IAAI,KAAK,QAAQ,IAAI,KAAK,QAAQ,IAAI,KAAK,QAAQ,IAAI;AACjE;AACF,cAAI,aAAa,EAAG;AACpB,gBAAM,MAAM,MAAM,EAAE,GAAG,SAAS,QAAQ,SAAS,CAAC;AAAA,QACpD,OAAO;AACL,gBAAM,KAAK,QAAQ,oBAAoB,QAAQ,IAAI,IAAI,CAAC,GACtD,KAAK,QAAQ,oBAAoB,QAAQ,IAAI,IAAI,CAAC;AACpD,cAAI,QAAQ,IAAI,KAAK,QAAQ,IAAI,KAAK,QAAQ,IAAI,KAAK,QAAQ,IAAI;AACjE;AACF,gBAAM,MAAM,KAAK,EAAE,GAAG,SAAS,QAAQ,IAAI,GAAG,CAAC;AAAA,QACjD;AACA,gBAAQ,WAAW;AAAA,MACrB,MAAO,OAAM,IAAI,UAAU,mCAAmC;AAAA,IAChE;AAAA,IACA,QAAQ,OAAO,OAAO,SAAS;AAC7B,UAAI,CAAC,OAAO,KAAK,EAAG;AACpB,UAAI,CAAC,MAAM,OAAO;AAChB,cAAM,WAAW,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,MAAM,OAAO,QAAQ;AAClE,cAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,MAAM,MAAM,OAAO,CAAC;AACpD,cAAM,WAAW;AACjB,YAAI,QAAQ,GAAG;AACb,gBAAM,MAAM,QAAQ,KAAK;AACzB,kBAAQ,WAAW;AAAA,QACrB;AAAA,MACF;AACA,YAAM,QAAQ;AACd,cAAQ,aAAa;AAAA,IACvB;AAAA,IACA,UAAU,OAAO,SAAS;AACxB,YAAM,OAAO,QAAQ,WAAW,gBAAgB,QAAQ,KAAK;AAC7D,UAAI,QAAQ,MAAM,YAAY;AAC5B,cAAM,MAAM,WAAW,QAAQ,WAAW,gBAAgB,MAAM;AAChE,cAAM,aAAa;AAAA,MACrB;AACA,YAAM,EAAE,OAAO,OAAO,IAAI,QAAQ,QAChC,OAAO,MAAM,MAAO,MACpB,MAAM,MAAM;AACd,eAAS,IAAI,GAAG,IAAI,QAAQ;AAC1B,iBAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,gBAAM,QACH,IAAI,MAAM,MAAM,SAAU,MAAM,MAAM,QACtC,IAAI,MAAM,MAAM;AACnB,gBAAM,QACF,KAAK;AAAA,YACH,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,MAAM,UAAU,KAAK,CAAC,CAAC,IAAI;AAAA,UAC3D,IAAI,GACN,KAAK,IAAI,QAAQ,KAAK;AACxB,eAAK,CAAC,IAAI,IAAI,KAAK;AACnB,eAAK,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;AAC3B,eAAK,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;AAC3B,eAAK,IAAI,CAAC,IAAI;AAAA,QAChB;AACF,cAAQ,OAAO,WAAW,IAAI,EAAG,aAAa,MAAM,OAAQ,GAAG,CAAC;AAAA,IAClE;AAAA,IACA,QAAQ,OAAO;AACb,YAAM,MAAM,QAAQ;AACpB,YAAM,QAAQ;AACd,YAAM,MAAM;AAAA,IACd;AAAA,EACF,CAAC;AACH;AACA,MAAM,qBAAqC,+BAAe,iBAAiB;AAC3E,MAAM,gBAAgC,+BAAe,YAAY;AACjE,MAAM,oBAAoC,+BAAe,gBAAgB;AAOlE,SAAS,aACd,UAA+B,CAAC,GACL;AAC3B,SAAO,mBAAmB,mBAAmB,OAAO,CAAC;AACvD;AAOO,SAAS,QACd,UAA0B,CAAC,GACA;AAC3B,SAAO,cAAc,cAAc,OAAO,CAAC;AAC7C;AAOO,SAAS,YACd,UAA8B,CAAC,GACJ;AAC3B,SAAO,kBAAkB,kBAAkB,OAAO,CAAC;AACrD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TextureRecipe } from
|
|
1
|
+
import type { TextureRecipe } from "../../../lib/textures/texture.js";
|
|
2
2
|
export { useTexture } from "@pibbl/core";
|
|
3
3
|
/**
|
|
4
4
|
* Seed, feature scale, and detail controls shared by static material recipes.
|
|
@@ -18,23 +18,8 @@ export interface MaterialOptions {
|
|
|
18
18
|
/** Material-specific distortion, grain strength, or cellular jitter. See {@link MaterialOptions}. */
|
|
19
19
|
readonly detail?: number;
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
*
|
|
24
|
-
* @see {@link reactionDiffusion}
|
|
25
|
-
*/
|
|
26
|
-
export interface ReactionDiffusionOptions {
|
|
27
|
-
/**
|
|
28
|
-
* Seed used for deterministic sampling or simulation initialization. See
|
|
29
|
-
* {@link ReactionDiffusionOptions}.
|
|
30
|
-
*/
|
|
31
|
-
readonly seed?: number;
|
|
32
|
-
/**
|
|
33
|
-
* Named pattern configuration used to initialize the simulation. See
|
|
34
|
-
* {@link ReactionDiffusionOptions}.
|
|
35
|
-
*/
|
|
36
|
-
readonly preset?: "spots" | "stripes";
|
|
37
|
-
}
|
|
21
|
+
export type { ReactionDiffusionOptions } from "./gray-scott.js";
|
|
22
|
+
import { type ReactionDiffusionOptions } from "./gray-scott.js";
|
|
38
23
|
/**
|
|
39
24
|
* Paint, stir, pause, or reset commands accepted by a reaction-diffusion texture.
|
|
40
25
|
*
|
|
@@ -8,6 +8,9 @@ import {
|
|
|
8
8
|
import { InkSimulation } from "./simulation.js";
|
|
9
9
|
import { paletteLut, texturePalettes, validateSeed } from "./palette.js";
|
|
10
10
|
import { useTexture } from "@pibbl/core";
|
|
11
|
+
import {
|
|
12
|
+
grayScottConfig
|
|
13
|
+
} from "./gray-scott.js";
|
|
11
14
|
function colorize(field, context, gain = 1) {
|
|
12
15
|
const ctx = context.canvas.getContext("2d");
|
|
13
16
|
const lut = paletteLut(context.palette ?? texturePalettes.porcelain);
|
|
@@ -63,19 +66,13 @@ function material(generate) {
|
|
|
63
66
|
const marble = /* @__PURE__ */ material(marbleField);
|
|
64
67
|
const paper = /* @__PURE__ */ material(paperField);
|
|
65
68
|
const cellular = /* @__PURE__ */ material(cellularField);
|
|
66
|
-
|
|
67
|
-
const seed = validateSeed(input.seed), preset = input.preset ?? "spots";
|
|
68
|
-
if (preset !== "spots" && preset !== "stripes")
|
|
69
|
-
throw new TypeError("Unknown ink preset.");
|
|
70
|
-
return { seed, preset };
|
|
71
|
-
}
|
|
69
|
+
const inkConfig = grayScottConfig;
|
|
72
70
|
function reset(state, context) {
|
|
73
|
-
const next = new InkSimulation(
|
|
74
|
-
context.canvas.width,
|
|
75
|
-
context.canvas.height,
|
|
76
|
-
state.config
|
|
77
|
-
|
|
78
|
-
);
|
|
71
|
+
const next = new InkSimulation({
|
|
72
|
+
width: context.canvas.width,
|
|
73
|
+
height: context.canvas.height,
|
|
74
|
+
...state.config
|
|
75
|
+
});
|
|
79
76
|
state.simulation.dispose();
|
|
80
77
|
state.simulation = next;
|
|
81
78
|
state.elapsed = 0;
|
|
@@ -88,12 +85,11 @@ const inkRecipe = /* @__PURE__ */ defineTexture({
|
|
|
88
85
|
const config = inkConfig(input);
|
|
89
86
|
context.requestFrame();
|
|
90
87
|
return {
|
|
91
|
-
simulation: new InkSimulation(
|
|
92
|
-
context.canvas.width,
|
|
93
|
-
context.canvas.height,
|
|
94
|
-
config
|
|
95
|
-
|
|
96
|
-
),
|
|
88
|
+
simulation: new InkSimulation({
|
|
89
|
+
width: context.canvas.width,
|
|
90
|
+
height: context.canvas.height,
|
|
91
|
+
...config
|
|
92
|
+
}),
|
|
97
93
|
config,
|
|
98
94
|
paused: false,
|
|
99
95
|
elapsed: 0,
|
|
@@ -102,8 +98,7 @@ const inkRecipe = /* @__PURE__ */ defineTexture({
|
|
|
102
98
|
},
|
|
103
99
|
update(state, input, context) {
|
|
104
100
|
const config = inkConfig(input);
|
|
105
|
-
if (config
|
|
106
|
-
return;
|
|
101
|
+
if (JSON.stringify(config) === JSON.stringify(state.config)) return;
|
|
107
102
|
state.config = config;
|
|
108
103
|
reset(state, context);
|
|
109
104
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/features/textures/lib/definitions.ts"],
|
|
4
|
-
"sourcesContent": ["import type { TextureRecipe } from '../../../lib/textures/texture.js';\nimport { rasterizeField, releaseField } from \"./wasm/memory.js\";\nimport { defineTexture, type TextureContext } from \"@pibbl/core\";\nimport {\n marbleField,\n paperField,\n cellularField,\n type MaterialGenerator,\n} from \"./material-field.js\";\nimport { InkSimulation } from \"./simulation.js\";\nimport { paletteLut, texturePalettes, validateSeed } from \"./palette.js\";\nexport { useTexture } from \"@pibbl/core\";\n/**\n * Seed, feature scale, and detail controls shared by static material recipes.\n *\n * @see {@link marble}\n * @see {@link paper}\n * @see {@link cellular}\n */\nexport interface MaterialOptions {\n /**\n * Seed used for deterministic sampling or simulation initialization. See {@link MaterialOptions}\n * .\n */\n readonly seed?: number;\n /** Feature frequency across the generated material. See {@link MaterialOptions}. */\n readonly scale?: number;\n /** Material-specific distortion, grain strength, or cellular jitter. See {@link MaterialOptions}. */\n readonly detail?: number;\n}\n/**\n * Seed and pattern preset for a reaction-diffusion recipe.\n *\n * @see {@link reactionDiffusion}\n */\nexport interface ReactionDiffusionOptions {\n /**\n * Seed used for deterministic sampling or simulation initialization. See\n * {@link ReactionDiffusionOptions}.\n */\n readonly seed?: number;\n /**\n * Named pattern configuration used to initialize the simulation. See\n * {@link ReactionDiffusionOptions}.\n */\n readonly preset?: \"spots\" | \"stripes\";\n}\n/**\n * Paint, stir, pause, or reset commands accepted by a reaction-diffusion texture.\n *\n * @see {@link reactionDiffusion}\n */\nexport type InkMessage =\n | {\n /** The literal \"paint\" identifying this variant. See {@link InkMessage}. */\n readonly type: \"paint\";\n /** Normalized horizontal texture coordinate. See {@link InkMessage}. */\n readonly u: number;\n /** Normalized vertical texture coordinate. See {@link InkMessage}. */\n readonly v: number;\n /** Radius in the coordinate system of this geometry or effect. See {@link InkMessage}. */\n readonly radius?: number;\n /** Magnitude of the displacement or brush effect. See {@link InkMessage}. */\n readonly strength?: number;\n }\n | {\n /** The literal \"stir\" identifying this variant. See {@link InkMessage}. */\n readonly type: \"stir\";\n /** Normalized horizontal texture coordinate. See {@link InkMessage}. */\n readonly u: number;\n /** Normalized vertical texture coordinate. See {@link InkMessage}. */\n readonly v: number;\n /** Normalized displacement of the existing field, not a paint dose. */\n readonly du: number;\n /** Normalized vertical displacement of the texture field. See {@link InkMessage}. */\n readonly dv: number;\n /** Influence radius in texture cells. */\n readonly radius?: number;\n }\n | {\n /** The literal \"pause\" identifying this variant. See {@link InkMessage}. */\n readonly type: \"pause\";\n /** Whether simulation or playback advancement is suspended. See {@link InkMessage}. */\n readonly paused: boolean;\n }\n | {\n /** The literal \"reset\" identifying this variant. See {@link InkMessage}. */\n readonly type: \"reset\";\n };\nfunction colorize(field: Float32Array, context: TextureContext, gain = 1) {\n const ctx = context.canvas.getContext(\"2d\")!;\n const lut = paletteLut(context.palette ?? texturePalettes.porcelain);\n const raster = rasterizeField(field, lut, gain);\n if (!raster) throw new Error(\"Texture field has no WASM owner.\");\n ctx.putImageData(raster.image, 0, 0);\n}\nfunction materialConfig(config: MaterialOptions) {\n const seed = validateSeed(config.seed),\n scale = config.scale ?? 6,\n detail = config.detail ?? 0.65;\n if (\n !Number.isFinite(scale) ||\n scale < 1 ||\n scale > 32 ||\n !Number.isFinite(detail) ||\n detail < 0 ||\n detail > 1\n )\n throw new RangeError(\"Material scale must be 1..32 and detail 0..1.\");\n return { seed, scale, detail };\n}\nfunction material(generate: MaterialGenerator) {\n const recipe = defineTexture<\n MaterialOptions,\n { config: ReturnType<typeof materialConfig>; field: Float32Array }\n >({\n create(context, input) {\n const config = materialConfig(input);\n return {\n config,\n field: generate(\n context.canvas.width,\n context.canvas.height,\n config.seed,\n config.scale,\n config.detail,\n ),\n };\n },\n update(state, input, context) {\n const config = materialConfig(input);\n if (JSON.stringify(config) === JSON.stringify(state.config)) return;\n state.field = generate(\n context.canvas.width,\n context.canvas.height,\n config.seed,\n config.scale,\n config.detail,\n state.field,\n );\n state.config = config;\n context.invalidate();\n },\n rasterize(state, context) {\n colorize(state.field, context);\n },\n dispose(state) {\n releaseField(state.field);\n state.field = new Float32Array(0);\n },\n });\n return (options: MaterialOptions = {}) => recipe(options);\n}\n/**\n * Creates a seeded marble texture recipe with configurable feature scale and distortion.\n *\n * @param options - Seed, feature scale, and detail settings. See {@link MaterialOptions}.\n * @returns A procedural material recipe for useTexture. See {@link TextureRecipe}.\n *\n * @see {@link MaterialOptions}\n * @see {@link TextureRecipe}\n */\nexport const marble = /* @__PURE__ */ material(marbleField);\n/**\n * Creates a seeded paper texture recipe with configurable feature scale and grain.\n *\n * @param options - Seed, feature scale, and detail settings. See {@link MaterialOptions}.\n * @returns A procedural material recipe for useTexture. See {@link TextureRecipe}.\n *\n * @see {@link MaterialOptions}\n * @see {@link TextureRecipe}\n */\nexport const paper = /* @__PURE__ */ material(paperField);\n/**\n * Creates a seeded cellular texture recipe with configurable feature scale and jitter.\n *\n * @param options - Seed, feature scale, and detail settings. See {@link MaterialOptions}.\n * @returns A procedural material recipe for useTexture. See {@link TextureRecipe}.\n *\n * @see {@link MaterialOptions}\n * @see {@link TextureRecipe}\n */\nexport const cellular = /* @__PURE__ */ material(cellularField);\nfunction inkConfig(input: ReactionDiffusionOptions) {\n const seed = validateSeed(input.seed),\n preset = input.preset ?? \"spots\";\n if (preset !== \"spots\" && preset !== \"stripes\")\n throw new TypeError(\"Unknown ink preset.\");\n return { seed, preset };\n}\ninterface InkState {\n simulation: InkSimulation;\n config: ReturnType<typeof inkConfig>;\n paused: boolean;\n elapsed: number;\n fresh: boolean;\n}\nfunction reset(state: InkState, context: TextureContext) {\n const next = new InkSimulation(\n context.canvas.width,\n context.canvas.height,\n state.config.seed,\n state.config.preset,\n );\n state.simulation.dispose();\n state.simulation = next;\n state.elapsed = 0;\n state.fresh = true;\n context.invalidate();\n}\nconst inkRecipe = /* @__PURE__ */ defineTexture<\n ReactionDiffusionOptions,\n InkState,\n InkMessage\n>({\n defaultPlacement: { mode: \"stretch\" },\n create(context, input) {\n const config = inkConfig(input);\n context.requestFrame();\n return {\n simulation: new InkSimulation(\n context.canvas.width,\n context.canvas.height,\n config.seed,\n config.preset,\n ),\n config,\n paused: false,\n elapsed: 0,\n fresh: true,\n };\n },\n update(state, input, context) {\n const config = inkConfig(input);\n if (\n config.seed === state.config.seed &&\n config.preset === state.config.preset\n )\n return;\n state.config = config;\n reset(state, context);\n },\n receive(state, message, context) {\n if (message.type === \"pause\") {\n state.paused = message.paused;\n state.elapsed = 0;\n state.fresh = true;\n if (!state.paused) context.requestFrame();\n } else if (message.type === \"reset\") reset(state, context);\n else if (message.type === \"stir\") {\n const radius = message.radius ?? 16;\n if (\n ![message.u, message.v, message.du, message.dv, radius].every(\n Number.isFinite,\n ) ||\n radius <= 0 ||\n radius > 128 ||\n Math.abs(message.du) > 1 ||\n Math.abs(message.dv) > 1\n )\n throw new RangeError(\"Invalid ink stir message.\");\n if (message.u < 0 || message.u > 1 || message.v < 0 || message.v > 1)\n return;\n state.simulation.stir(\n message.u * context.canvas.width,\n message.v * context.canvas.height,\n message.du * context.canvas.width,\n message.dv * context.canvas.height,\n radius,\n );\n context.invalidate();\n } else if (message.type === \"paint\") {\n const radius = message.radius ?? 6,\n strength = message.strength ?? 0.8;\n if (\n ![message.u, message.v, radius, strength].every(Number.isFinite) ||\n radius <= 0 ||\n radius > 128 ||\n strength < 0 ||\n strength > 1\n )\n throw new RangeError(\"Invalid ink paint message.\");\n if (message.u < 0 || message.v < 0 || message.u > 1 || message.v > 1)\n return;\n state.simulation.paint(\n message.u * context.canvas.width,\n message.v * context.canvas.height,\n radius,\n strength,\n );\n context.invalidate();\n } else throw new TypeError(\"Unknown ink message.\");\n },\n advance(state, frame, context) {\n if (state.paused) return;\n if (!state.fresh) {\n state.elapsed += Math.min(50, frame.delta);\n const steps = Math.min(24, Math.floor(state.elapsed * 0.48 + 1e-9));\n state.elapsed -= steps / 0.48;\n if (steps) {\n state.simulation.advance(steps);\n context.invalidate();\n }\n }\n state.fresh = false;\n context.requestFrame();\n },\n rasterize(state, context) {\n colorize(state.simulation.b, context, 650 / 255);\n },\n dispose(state) {\n state.simulation.dispose();\n },\n});\n/**\n * Creates a stateful reaction-diffusion texture recipe supporting paint, stirring, pause, and\n * reset\n * messages.\n *\n * @param options - Reaction and diffusion parameters, initialization, and rendering options. See\n * {@link ReactionDiffusionOptions} .\n * @returns A reaction-diffusion texture recipe for useTexture.\n *\n * @see {@link ReactionDiffusionOptions}\n */\nexport function reactionDiffusion(options: ReactionDiffusionOptions = {}) {\n return inkRecipe(options);\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,gBAAgB,oBAAoB;AAC7C,SAAS,qBAA0C;AACnD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,qBAAqB;AAC9B,SAAS,YAAY,iBAAiB,oBAAoB;AAC1D,SAAS,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import type { TextureRecipe } from \"../../../lib/textures/texture.js\";\nimport { rasterizeField, releaseField } from \"./wasm/memory.js\";\nimport { defineTexture, type TextureContext } from \"@pibbl/core\";\nimport {\n marbleField,\n paperField,\n cellularField,\n type MaterialGenerator,\n} from \"./material-field.js\";\nimport { InkSimulation } from \"./simulation.js\";\nimport { paletteLut, texturePalettes, validateSeed } from \"./palette.js\";\nexport { useTexture } from \"@pibbl/core\";\n/**\n * Seed, feature scale, and detail controls shared by static material recipes.\n *\n * @see {@link marble}\n * @see {@link paper}\n * @see {@link cellular}\n */\nexport interface MaterialOptions {\n /**\n * Seed used for deterministic sampling or simulation initialization. See {@link MaterialOptions}\n * .\n */\n readonly seed?: number;\n /** Feature frequency across the generated material. See {@link MaterialOptions}. */\n readonly scale?: number;\n /** Material-specific distortion, grain strength, or cellular jitter. See {@link MaterialOptions}. */\n readonly detail?: number;\n}\nexport type { ReactionDiffusionOptions } from \"./gray-scott.js\";\nimport {\n grayScottConfig,\n type ReactionDiffusionOptions,\n} from \"./gray-scott.js\";\n/**\n * Paint, stir, pause, or reset commands accepted by a reaction-diffusion texture.\n *\n * @see {@link reactionDiffusion}\n */\nexport type InkMessage =\n | {\n /** The literal \"paint\" identifying this variant. See {@link InkMessage}. */\n readonly type: \"paint\";\n /** Normalized horizontal texture coordinate. See {@link InkMessage}. */\n readonly u: number;\n /** Normalized vertical texture coordinate. See {@link InkMessage}. */\n readonly v: number;\n /** Radius in the coordinate system of this geometry or effect. See {@link InkMessage}. */\n readonly radius?: number;\n /** Magnitude of the displacement or brush effect. See {@link InkMessage}. */\n readonly strength?: number;\n }\n | {\n /** The literal \"stir\" identifying this variant. See {@link InkMessage}. */\n readonly type: \"stir\";\n /** Normalized horizontal texture coordinate. See {@link InkMessage}. */\n readonly u: number;\n /** Normalized vertical texture coordinate. See {@link InkMessage}. */\n readonly v: number;\n /** Normalized displacement of the existing field, not a paint dose. */\n readonly du: number;\n /** Normalized vertical displacement of the texture field. See {@link InkMessage}. */\n readonly dv: number;\n /** Influence radius in texture cells. */\n readonly radius?: number;\n }\n | {\n /** The literal \"pause\" identifying this variant. See {@link InkMessage}. */\n readonly type: \"pause\";\n /** Whether simulation or playback advancement is suspended. See {@link InkMessage}. */\n readonly paused: boolean;\n }\n | {\n /** The literal \"reset\" identifying this variant. See {@link InkMessage}. */\n readonly type: \"reset\";\n };\nfunction colorize(field: Float32Array, context: TextureContext, gain = 1) {\n const ctx = context.canvas.getContext(\"2d\")!;\n const lut = paletteLut(context.palette ?? texturePalettes.porcelain);\n const raster = rasterizeField(field, lut, gain);\n if (!raster) throw new Error(\"Texture field has no WASM owner.\");\n ctx.putImageData(raster.image, 0, 0);\n}\nfunction materialConfig(config: MaterialOptions) {\n const seed = validateSeed(config.seed),\n scale = config.scale ?? 6,\n detail = config.detail ?? 0.65;\n if (\n !Number.isFinite(scale) ||\n scale < 1 ||\n scale > 32 ||\n !Number.isFinite(detail) ||\n detail < 0 ||\n detail > 1\n )\n throw new RangeError(\"Material scale must be 1..32 and detail 0..1.\");\n return { seed, scale, detail };\n}\nfunction material(generate: MaterialGenerator) {\n const recipe = defineTexture<\n MaterialOptions,\n { config: ReturnType<typeof materialConfig>; field: Float32Array }\n >({\n create(context, input) {\n const config = materialConfig(input);\n return {\n config,\n field: generate(\n context.canvas.width,\n context.canvas.height,\n config.seed,\n config.scale,\n config.detail,\n ),\n };\n },\n update(state, input, context) {\n const config = materialConfig(input);\n if (JSON.stringify(config) === JSON.stringify(state.config)) return;\n state.field = generate(\n context.canvas.width,\n context.canvas.height,\n config.seed,\n config.scale,\n config.detail,\n state.field,\n );\n state.config = config;\n context.invalidate();\n },\n rasterize(state, context) {\n colorize(state.field, context);\n },\n dispose(state) {\n releaseField(state.field);\n state.field = new Float32Array(0);\n },\n });\n return (options: MaterialOptions = {}) => recipe(options);\n}\n/**\n * Creates a seeded marble texture recipe with configurable feature scale and distortion.\n *\n * @param options - Seed, feature scale, and detail settings. See {@link MaterialOptions}.\n * @returns A procedural material recipe for useTexture. See {@link TextureRecipe}.\n *\n * @see {@link MaterialOptions}\n * @see {@link TextureRecipe}\n */\nexport const marble = /* @__PURE__ */ material(marbleField);\n/**\n * Creates a seeded paper texture recipe with configurable feature scale and grain.\n *\n * @param options - Seed, feature scale, and detail settings. See {@link MaterialOptions}.\n * @returns A procedural material recipe for useTexture. See {@link TextureRecipe}.\n *\n * @see {@link MaterialOptions}\n * @see {@link TextureRecipe}\n */\nexport const paper = /* @__PURE__ */ material(paperField);\n/**\n * Creates a seeded cellular texture recipe with configurable feature scale and jitter.\n *\n * @param options - Seed, feature scale, and detail settings. See {@link MaterialOptions}.\n * @returns A procedural material recipe for useTexture. See {@link TextureRecipe}.\n *\n * @see {@link MaterialOptions}\n * @see {@link TextureRecipe}\n */\nexport const cellular = /* @__PURE__ */ material(cellularField);\nconst inkConfig = grayScottConfig;\ninterface InkState {\n simulation: InkSimulation;\n config: ReturnType<typeof inkConfig>;\n paused: boolean;\n elapsed: number;\n fresh: boolean;\n}\nfunction reset(state: InkState, context: TextureContext) {\n const next = new InkSimulation({\n width: context.canvas.width,\n height: context.canvas.height,\n ...state.config,\n });\n state.simulation.dispose();\n state.simulation = next;\n state.elapsed = 0;\n state.fresh = true;\n context.invalidate();\n}\nconst inkRecipe = /* @__PURE__ */ defineTexture<\n ReactionDiffusionOptions,\n InkState,\n InkMessage\n>({\n defaultPlacement: { mode: \"stretch\" },\n create(context, input) {\n const config = inkConfig(input);\n context.requestFrame();\n return {\n simulation: new InkSimulation({\n width: context.canvas.width,\n height: context.canvas.height,\n ...config,\n }),\n config,\n paused: false,\n elapsed: 0,\n fresh: true,\n };\n },\n update(state, input, context) {\n const config = inkConfig(input);\n if (JSON.stringify(config) === JSON.stringify(state.config)) return;\n state.config = config;\n reset(state, context);\n },\n receive(state, message, context) {\n if (message.type === \"pause\") {\n state.paused = message.paused;\n state.elapsed = 0;\n state.fresh = true;\n if (!state.paused) context.requestFrame();\n } else if (message.type === \"reset\") reset(state, context);\n else if (message.type === \"stir\") {\n const radius = message.radius ?? 16;\n if (\n ![message.u, message.v, message.du, message.dv, radius].every(\n Number.isFinite,\n ) ||\n radius <= 0 ||\n radius > 128 ||\n Math.abs(message.du) > 1 ||\n Math.abs(message.dv) > 1\n )\n throw new RangeError(\"Invalid ink stir message.\");\n if (message.u < 0 || message.u > 1 || message.v < 0 || message.v > 1)\n return;\n state.simulation.stir(\n message.u * context.canvas.width,\n message.v * context.canvas.height,\n message.du * context.canvas.width,\n message.dv * context.canvas.height,\n radius,\n );\n context.invalidate();\n } else if (message.type === \"paint\") {\n const radius = message.radius ?? 6,\n strength = message.strength ?? 0.8;\n if (\n ![message.u, message.v, radius, strength].every(Number.isFinite) ||\n radius <= 0 ||\n radius > 128 ||\n strength < 0 ||\n strength > 1\n )\n throw new RangeError(\"Invalid ink paint message.\");\n if (message.u < 0 || message.v < 0 || message.u > 1 || message.v > 1)\n return;\n state.simulation.paint(\n message.u * context.canvas.width,\n message.v * context.canvas.height,\n radius,\n strength,\n );\n context.invalidate();\n } else throw new TypeError(\"Unknown ink message.\");\n },\n advance(state, frame, context) {\n if (state.paused) return;\n if (!state.fresh) {\n state.elapsed += Math.min(50, frame.delta);\n const steps = Math.min(24, Math.floor(state.elapsed * 0.48 + 1e-9));\n state.elapsed -= steps / 0.48;\n if (steps) {\n state.simulation.advance(steps);\n context.invalidate();\n }\n }\n state.fresh = false;\n context.requestFrame();\n },\n rasterize(state, context) {\n colorize(state.simulation.b, context, 650 / 255);\n },\n dispose(state) {\n state.simulation.dispose();\n },\n});\n/**\n * Creates a stateful reaction-diffusion texture recipe supporting paint, stirring, pause, and\n * reset\n * messages.\n *\n * @param options - Reaction and diffusion parameters, initialization, and rendering options. See\n * {@link ReactionDiffusionOptions} .\n * @returns A reaction-diffusion texture recipe for useTexture.\n *\n * @see {@link ReactionDiffusionOptions}\n */\nexport function reactionDiffusion(options: ReactionDiffusionOptions = {}) {\n return inkRecipe(options);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { type TextureRecipe } from "@pibbl/core";
|
|
2
|
+
import type { PatternMotionOptions } from "./patterns.js";
|
|
3
|
+
/** Seamless circular dots with optional stagger and seeded displacement. @see {@link polkaDots} */
|
|
4
|
+
export interface PolkaDotsOptions extends PatternMotionOptions {
|
|
5
|
+
/** Integer columns, 1–64; default 12. See {@link PolkaDotsOptions}. */
|
|
6
|
+
readonly columns?: number;
|
|
7
|
+
/** Even integer rows, 2–64; default 12, preserving stagger across the seam. See {@link PolkaDotsOptions}. */
|
|
8
|
+
readonly rows?: number;
|
|
9
|
+
/** Radius in cell fractions, 0–0.5; default 0.3. See {@link PolkaDotsOptions}. */
|
|
10
|
+
readonly radius?: number;
|
|
11
|
+
/** Alternate-row horizontal offset in cell fractions, 0–1; default 0. See {@link PolkaDotsOptions}. */
|
|
12
|
+
readonly stagger?: number;
|
|
13
|
+
/** Seeded center displacement per axis in cell fractions, 0–0.5; default 0. See {@link PolkaDotsOptions}. */
|
|
14
|
+
readonly jitter?: number;
|
|
15
|
+
/** Unsigned 32-bit variation seed; default 42. See {@link PolkaDotsOptions}. */
|
|
16
|
+
readonly seed?: number;
|
|
17
|
+
}
|
|
18
|
+
/** A periodic tonal field expressed as varying dot sizes. @see {@link halftone} */
|
|
19
|
+
export interface HalftoneOptions extends PatternMotionOptions {
|
|
20
|
+
/** Integer columns, 1–64; default 24. See {@link HalftoneOptions}. */
|
|
21
|
+
readonly columns?: number;
|
|
22
|
+
/** Even integer rows, 2–64; default 24. See {@link HalftoneOptions}. */
|
|
23
|
+
readonly rows?: number;
|
|
24
|
+
/** Smallest dot radius in cell fractions, 0–0.5; default 0.05. See {@link HalftoneOptions}. */
|
|
25
|
+
readonly minRadius?: number;
|
|
26
|
+
/** Largest dot radius in cell fractions, minRadius–0.5; default 0.45. See {@link HalftoneOptions}. */
|
|
27
|
+
readonly maxRadius?: number;
|
|
28
|
+
/** Integer horizontal tonal periods, 0–16; default 1. See {@link HalftoneOptions}. */
|
|
29
|
+
readonly cyclesX?: number;
|
|
30
|
+
/** Integer vertical tonal periods, 0–16; default 1. See {@link HalftoneOptions}. */
|
|
31
|
+
readonly cyclesY?: number;
|
|
32
|
+
/** Tonal wave amplitude, 0–1; default 0.7. See {@link HalftoneOptions}. */
|
|
33
|
+
readonly contrast?: number;
|
|
34
|
+
/** Alternate-row offset in cell fractions, 0–1; default 0.5. See {@link HalftoneOptions}. */
|
|
35
|
+
readonly stagger?: number;
|
|
36
|
+
}
|
|
37
|
+
/** Seeded connecting quarter-circle tiles. @see {@link truchet} */
|
|
38
|
+
export interface TruchetOptions extends PatternMotionOptions {
|
|
39
|
+
/** Integer columns, 1–64; default 8. See {@link TruchetOptions}. */
|
|
40
|
+
readonly columns?: number;
|
|
41
|
+
/** Integer rows, 1–64; default 8. See {@link TruchetOptions}. */
|
|
42
|
+
readonly rows?: number;
|
|
43
|
+
/** Stroke width in cell fractions, 0–0.5; default 0.12. See {@link TruchetOptions}. */
|
|
44
|
+
readonly lineWidth?: number;
|
|
45
|
+
/** Fraction of tiles with the first orientation, 0–1; default 0.5. See {@link TruchetOptions}. */
|
|
46
|
+
readonly orientationBias?: number;
|
|
47
|
+
/** Unsigned 32-bit orientation seed; default 42. See {@link TruchetOptions}. */
|
|
48
|
+
readonly seed?: number;
|
|
49
|
+
}
|
|
50
|
+
/** One band in an ordered plaid repeat; colors are named keys. @see {@link PlaidOptions} */
|
|
51
|
+
export interface PlaidBand<Key extends string = string> {
|
|
52
|
+
/** Positive relative width; all widths on an axis are normalized together. See {@link PlaidBand}. */
|
|
53
|
+
readonly width: number;
|
|
54
|
+
/** A key from the plaid's colors dictionary. See {@link PlaidBand}. */
|
|
55
|
+
readonly color: Key;
|
|
56
|
+
}
|
|
57
|
+
/** A plaid's named colors, ordered bands, and crossing balance. @see {@link plaid} */
|
|
58
|
+
export interface PlaidOptions<Colors extends Readonly<Record<string, string>> = Readonly<Record<string, string>>> extends PatternMotionOptions {
|
|
59
|
+
/** Dictionary of 1–16 opaque #RRGGBB colors. See {@link PlaidOptions}. */
|
|
60
|
+
readonly colors: Colors;
|
|
61
|
+
/** Ordered horizontal bands, 1–32, referencing existing color keys. See {@link PlaidOptions}. */
|
|
62
|
+
readonly horizontal: readonly PlaidBand<NoInfer<Extract<keyof Colors, string>>>[];
|
|
63
|
+
/** Ordered vertical bands, 1–32, referencing existing color keys. See {@link PlaidOptions}. */
|
|
64
|
+
readonly vertical: readonly PlaidBand<NoInfer<Extract<keyof Colors, string>>>[];
|
|
65
|
+
/** Horizontal contribution at crossings, 0–1; default 0.5. See {@link PlaidOptions}. */
|
|
66
|
+
readonly crossing?: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Creates a seamless dot lattice using palette endpoints.
|
|
70
|
+
* @param options - Dot geometry and motion.
|
|
71
|
+
* @returns A mountable texture recipe.
|
|
72
|
+
* @see {@link PolkaDotsOptions}
|
|
73
|
+
*/
|
|
74
|
+
export declare function polkaDots(options?: PolkaDotsOptions): TextureRecipe;
|
|
75
|
+
/**
|
|
76
|
+
* Creates seamless varying-size dots from a periodic tonal field.
|
|
77
|
+
* @param options - Dot sizes, tonal periods, and motion.
|
|
78
|
+
* @returns A mountable texture recipe.
|
|
79
|
+
* @see {@link HalftoneOptions}
|
|
80
|
+
*/
|
|
81
|
+
export declare function halftone(options?: HalftoneOptions): TextureRecipe;
|
|
82
|
+
/**
|
|
83
|
+
* Creates seeded quarter-circle tiles that connect across every edge.
|
|
84
|
+
* @param options - Tile counts, stroke width, seed, and motion.
|
|
85
|
+
* @returns A mountable texture recipe.
|
|
86
|
+
* @see {@link TruchetOptions}
|
|
87
|
+
*/
|
|
88
|
+
export declare function truchet(options?: TruchetOptions): TextureRecipe;
|
|
89
|
+
/**
|
|
90
|
+
* Creates plaid using checked color keys and ordered relative-width bands.
|
|
91
|
+
* @param options - Named colors, bands, crossing balance, and motion.
|
|
92
|
+
* @returns A mountable texture recipe.
|
|
93
|
+
* @see {@link PlaidOptions}
|
|
94
|
+
*/
|
|
95
|
+
export declare function plaid<const Colors extends Readonly<Record<string, string>>>(options: PlaidOptions<Colors>): TextureRecipe;
|
|
96
|
+
/** Named-color band configurations for gingham, tartan, and windowpane patterns. @see {@link plaid} */
|
|
97
|
+
export declare const plaidPresets: Readonly<{
|
|
98
|
+
/** Equal-width alternating bands. See {@link plaidPresets}. */
|
|
99
|
+
gingham: Readonly<{
|
|
100
|
+
colors: Readonly<{
|
|
101
|
+
background: "#f5e9d3";
|
|
102
|
+
primary: "#304c48";
|
|
103
|
+
accent: "#c56948";
|
|
104
|
+
}>;
|
|
105
|
+
horizontal: readonly Readonly<{
|
|
106
|
+
width: number;
|
|
107
|
+
color: "accent" | "background" | "primary";
|
|
108
|
+
}>[];
|
|
109
|
+
vertical: readonly Readonly<{
|
|
110
|
+
width: number;
|
|
111
|
+
color: "accent" | "background" | "primary";
|
|
112
|
+
}>[];
|
|
113
|
+
crossing: 0.5;
|
|
114
|
+
}>;
|
|
115
|
+
/** Symmetric bands with narrow accent lines. See {@link plaidPresets}. */
|
|
116
|
+
tartan: Readonly<{
|
|
117
|
+
colors: Readonly<{
|
|
118
|
+
background: "#f5e9d3";
|
|
119
|
+
primary: "#304c48";
|
|
120
|
+
accent: "#c56948";
|
|
121
|
+
}>;
|
|
122
|
+
horizontal: readonly Readonly<{
|
|
123
|
+
width: number;
|
|
124
|
+
color: "accent" | "background" | "primary";
|
|
125
|
+
}>[];
|
|
126
|
+
vertical: readonly Readonly<{
|
|
127
|
+
width: number;
|
|
128
|
+
color: "accent" | "background" | "primary";
|
|
129
|
+
}>[];
|
|
130
|
+
crossing: 0.5;
|
|
131
|
+
}>;
|
|
132
|
+
/** Narrow crossing lines on a broad background. See {@link plaidPresets}. */
|
|
133
|
+
windowpane: Readonly<{
|
|
134
|
+
colors: Readonly<{
|
|
135
|
+
background: "#f5e9d3";
|
|
136
|
+
primary: "#304c48";
|
|
137
|
+
accent: "#c56948";
|
|
138
|
+
}>;
|
|
139
|
+
horizontal: readonly Readonly<{
|
|
140
|
+
width: number;
|
|
141
|
+
color: "accent" | "background" | "primary";
|
|
142
|
+
}>[];
|
|
143
|
+
vertical: readonly Readonly<{
|
|
144
|
+
width: number;
|
|
145
|
+
color: "accent" | "background" | "primary";
|
|
146
|
+
}>[];
|
|
147
|
+
crossing: 0.5;
|
|
148
|
+
}>;
|
|
149
|
+
}>;
|