@woosh/meep-engine 3.60.1 → 3.60.2
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/package.json +1 -1
- package/src/shade/playground/sh_exponential/main.js +2 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +4 -0
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +3 -5
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts +13 -5
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/execute_filter_environment_map.js +133 -7
- package/src/shade/renderer/light/environment/graph_filter_environment_map.d.ts +9 -0
- package/src/shade/renderer/light/environment/graph_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/graph_filter_environment_map.js +33 -4
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.d.ts +13 -0
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.js +169 -0
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.d.ts +3 -0
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.js +105 -0
- package/src/shade/renderer/light/environment/sphere_probe_lod_to_roughness.d.ts +10 -0
- package/src/shade/renderer/light/environment/sphere_probe_lod_to_roughness.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/sphere_probe_lod_to_roughness.js +23 -0
- package/src/shade/renderer/shader/chunk/light/probe/chunk_probe_visibility_weight.d.ts +8 -4
- package/src/shade/renderer/shader/chunk/light/probe/chunk_probe_visibility_weight.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/light/probe/chunk_probe_visibility_weight.js +9 -5
- package/src/view/elements/progress/segmented/GhostTrail.d.ts +6 -0
- package/src/view/elements/progress/segmented/GhostTrail.d.ts.map +1 -1
- package/src/view/elements/progress/segmented/GhostTrail.js +14 -0
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts +55 -19
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts.map +1 -1
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.js +173 -120
- package/src/view/elements/progress/segmented/playground/main.js +18 -11
- package/src/view/elements/progress/segmented/segment_cell_extent.d.ts +14 -0
- package/src/view/elements/progress/segmented/segment_cell_extent.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/segment_cell_extent.js +44 -0
- package/src/view/elements/progress/segmented/segment_mask_url.d.ts +24 -0
- package/src/view/elements/progress/segmented/segment_mask_url.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/segment_mask_url.js +74 -0
- package/src/view/elements/progress/segmented/segment_mask_width.d.ts +18 -0
- package/src/view/elements/progress/segmented/segment_mask_width.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/segment_mask_width.js +46 -0
- package/src/view/elements/progress/segmented/segmented-resource-bar.css +6 -10
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @type {HTMLCanvasElement|null}
|
|
3
|
+
*/
|
|
4
|
+
let canvas = null;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Whether masks can be drawn here. Keyed on `OffscreenCanvas`, which every browser that draws a canvas has and
|
|
8
|
+
* jsdom does not: jsdom's own canvas reports "not implemented" on the console for every call, so it is never asked.
|
|
9
|
+
* @returns {boolean}
|
|
10
|
+
*/
|
|
11
|
+
export function segment_mask_supported() {
|
|
12
|
+
return typeof OffscreenCanvas === 'function' && typeof document !== 'undefined';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A mask image of opaque columns, one device pixel tall, for a layer `width_device` device pixels wide: stretched
|
|
17
|
+
* over the layer with `mask-size: 100% 100%`, each column covers exactly the device pixels it was drawn on. CSS keeps
|
|
18
|
+
* painting the layer (its colour, gradient, height); the mask only decides which columns of it show.
|
|
19
|
+
*
|
|
20
|
+
* @param {number} width_device
|
|
21
|
+
* @param {number[]} columns [x, width, x, width, ...] in whole device pixels from the layer's left edge
|
|
22
|
+
* @param {number} column_count how many pairs of `columns` to draw
|
|
23
|
+
* @returns {string|null} a `url(...)` for `mask-image`, or null where masks cannot be drawn
|
|
24
|
+
*/
|
|
25
|
+
export function segment_mask_url(width_device, columns, column_count) {
|
|
26
|
+
if (!segment_mask_supported() || !(width_device > 0)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (canvas === null) {
|
|
31
|
+
canvas = document.createElement('canvas');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
canvas.width = width_device;
|
|
35
|
+
canvas.height = 1;
|
|
36
|
+
|
|
37
|
+
const ctx = canvas.getContext('2d');
|
|
38
|
+
|
|
39
|
+
if (ctx === null) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
ctx.clearRect(0, 0, width_device, 1);
|
|
44
|
+
ctx.fillStyle = '#000';
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < column_count; i++) {
|
|
47
|
+
ctx.fillRect(columns[i * 2], 0, columns[i * 2 + 1], 1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return `url(${canvas.toDataURL()})`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Put a mask from {@link segment_mask_url} on an element, sampled nearest so its columns stay whole, or take it off
|
|
55
|
+
* @param {HTMLElement} el
|
|
56
|
+
* @param {string|null} url
|
|
57
|
+
*/
|
|
58
|
+
export function segment_mask_apply(el, url) {
|
|
59
|
+
const style = el.style;
|
|
60
|
+
const value = url === null ? '' : url;
|
|
61
|
+
|
|
62
|
+
style.setProperty('mask-image', value);
|
|
63
|
+
style.setProperty('-webkit-mask-image', value);
|
|
64
|
+
|
|
65
|
+
if (url === null) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
style.setProperty('mask-size', '100% 100%');
|
|
70
|
+
style.setProperty('-webkit-mask-size', '100% 100%');
|
|
71
|
+
style.setProperty('mask-repeat', 'no-repeat');
|
|
72
|
+
style.setProperty('-webkit-mask-repeat', 'no-repeat');
|
|
73
|
+
style.setProperty('image-rendering', 'pixelated');
|
|
74
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The width to give a layer whose content is drawn in whole device pixels and stretched over it by a mask: the
|
|
3
|
+
* widest whole number of CSS pixels, no wider than `width_px`, that is also a whole number of device pixels.
|
|
4
|
+
*
|
|
5
|
+
* Measured in Chrome (90% to 300%): a masked layer whose width is not whole in both units is resampled when it is
|
|
6
|
+
* painted, and somewhere along it one device column is doubled or dropped, so one gap of a row of equal gaps paints
|
|
7
|
+
* a pixel wider or narrower than the rest. Whole in both, every column lands where it was drawn. The cost is up to a
|
|
8
|
+
* few CSS pixels at the layer's right end (at 125%, a multiple of 4).
|
|
9
|
+
*
|
|
10
|
+
* Where no such width lies within {@link SEARCH_CSS_PX} (a ratio like 2/3), it falls back to the whole device
|
|
11
|
+
* pixels that fit.
|
|
12
|
+
*
|
|
13
|
+
* @param {number} width_px the room there is, CSS pixels
|
|
14
|
+
* @param {number} ratio device pixels per CSS pixel
|
|
15
|
+
* @returns {number} the layer's width in device pixels; divided by `ratio`, its width in CSS pixels
|
|
16
|
+
*/
|
|
17
|
+
export function segment_mask_width(width_px: number, ratio: number): number;
|
|
18
|
+
//# sourceMappingURL=segment_mask_width.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment_mask_width.d.ts","sourceRoot":"","sources":["../../../../../../src/view/elements/progress/segmented/segment_mask_width.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;GAeG;AACH,6CAJW,MAAM,SACN,MAAM,GACJ,MAAM,CAmBlB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How far a scan gives up looking for a whole width that is also whole in device pixels, in CSS pixels
|
|
3
|
+
* @type {number}
|
|
4
|
+
*/
|
|
5
|
+
const SEARCH_CSS_PX = 12;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Tolerance for "a whole number of device pixels"
|
|
9
|
+
* @type {number}
|
|
10
|
+
*/
|
|
11
|
+
const WHOLE_TOLERANCE = 1e-6;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The width to give a layer whose content is drawn in whole device pixels and stretched over it by a mask: the
|
|
15
|
+
* widest whole number of CSS pixels, no wider than `width_px`, that is also a whole number of device pixels.
|
|
16
|
+
*
|
|
17
|
+
* Measured in Chrome (90% to 300%): a masked layer whose width is not whole in both units is resampled when it is
|
|
18
|
+
* painted, and somewhere along it one device column is doubled or dropped, so one gap of a row of equal gaps paints
|
|
19
|
+
* a pixel wider or narrower than the rest. Whole in both, every column lands where it was drawn. The cost is up to a
|
|
20
|
+
* few CSS pixels at the layer's right end (at 125%, a multiple of 4).
|
|
21
|
+
*
|
|
22
|
+
* Where no such width lies within {@link SEARCH_CSS_PX} (a ratio like 2/3), it falls back to the whole device
|
|
23
|
+
* pixels that fit.
|
|
24
|
+
*
|
|
25
|
+
* @param {number} width_px the room there is, CSS pixels
|
|
26
|
+
* @param {number} ratio device pixels per CSS pixel
|
|
27
|
+
* @returns {number} the layer's width in device pixels; divided by `ratio`, its width in CSS pixels
|
|
28
|
+
*/
|
|
29
|
+
export function segment_mask_width(width_px, ratio) {
|
|
30
|
+
if (!(width_px > 0) || !(ratio > 0)) {
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const widest = Math.floor(width_px);
|
|
35
|
+
|
|
36
|
+
for (let w = widest; w > 0 && w > widest - SEARCH_CSS_PX; w--) {
|
|
37
|
+
const device = w * ratio;
|
|
38
|
+
const whole = Math.round(device);
|
|
39
|
+
|
|
40
|
+
if (Math.abs(device - whole) <= WHOLE_TOLERANCE) {
|
|
41
|
+
return whole;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return Math.floor(width_px * ratio);
|
|
46
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
Theming: every colour, notch height and the ghost go through a --segmented-bar-* custom property with a
|
|
5
5
|
fallback, so a game re-skins the bar by defining the properties on the bar or any ancestor, without overriding a
|
|
6
|
-
selector. Each
|
|
6
|
+
selector. Each tier's layer carries its class_name; the three classes below are the ones SEGMENT_TIERS_DEFAULT
|
|
7
7
|
uses, and a game's own tiers may reuse them or style their own.
|
|
8
8
|
|
|
9
9
|
Import this from a style entry point, never from a logic module. Give the bar its width and height there; keep
|
|
@@ -61,14 +61,14 @@
|
|
|
61
61
|
background: var(--segmented-bar-fill-2-color, #7a5fd0);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
/* notches
|
|
64
|
+
/* notches: one layer per tier, the width of the bar, cut to its notches by a mask the view draws. Style the
|
|
65
|
+
layer as you would one notch: its colour, its height, from the top. */
|
|
65
66
|
|
|
66
67
|
.ui-segmented-resource-bar-view .notch {
|
|
67
68
|
position: absolute;
|
|
68
69
|
top: 0;
|
|
69
70
|
height: var(--segmented-bar-tick-height, 100%);
|
|
70
71
|
background: var(--segmented-bar-tick-color, rgba(0, 0, 0, 0.6));
|
|
71
|
-
box-shadow: var(--segmented-bar-tick-highlight, none);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
.ui-segmented-resource-bar-view .notch.segment-tier-minor {
|
|
@@ -86,7 +86,8 @@
|
|
|
86
86
|
background: var(--segmented-bar-tick-super-color, rgba(0, 0, 0, 0.85));
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/* cells
|
|
89
|
+
/* cells: one strip, the empty cells colour, cut into cells by a mask the view draws; the ghost and the fill run
|
|
90
|
+
along it and end on a cell edge (or part way across the one filling up) */
|
|
90
91
|
|
|
91
92
|
.ui-segmented-resource-bar-view.mode-cells {
|
|
92
93
|
/* the gaps between cells show the bar through them */
|
|
@@ -94,7 +95,7 @@
|
|
|
94
95
|
box-shadow: none;
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
.ui-segmented-resource-bar-view .cell {
|
|
98
|
+
.ui-segmented-resource-bar-view .cell-strip {
|
|
98
99
|
position: absolute;
|
|
99
100
|
top: 0;
|
|
100
101
|
bottom: 0;
|
|
@@ -119,11 +120,6 @@
|
|
|
119
120
|
background: var(--segmented-bar-cell-filled-color, #e8c25a);
|
|
120
121
|
}
|
|
121
122
|
|
|
122
|
-
/* a cell filling up one at a time, e.g. a round being loaded */
|
|
123
|
-
.ui-segmented-resource-bar-view .cell.partial > .cell-fill {
|
|
124
|
-
background: var(--segmented-bar-cell-partial-color, rgba(232, 194, 90, 0.6));
|
|
125
|
-
}
|
|
126
|
-
|
|
127
123
|
/* highlights (the view's `highlights` list) */
|
|
128
124
|
|
|
129
125
|
.ui-segmented-resource-bar-view > .highlights {
|