@three-blocks/devtools 1.0.0-alpha.176.g8ff8a72e6369
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/CHANGELOG.md +11 -0
- package/LICENSE +76 -0
- package/NOTICE +32 -0
- package/README.md +254 -0
- package/dist/browser/environment-bake.js +1 -0
- package/dist/browser/shader-capture.d.ts +45 -0
- package/dist/browser/shader-capture.js +3 -0
- package/dist/browser-smoke-76626IZQ.js +254 -0
- package/dist/chunk-26FK4CRS.js +6 -0
- package/dist/chunk-4EHPYBKA.cjs +1 -0
- package/dist/chunk-5L2VS3BN.js +2 -0
- package/dist/chunk-76WRV5MZ.js +7 -0
- package/dist/chunk-EI7MMDWY.js +1 -0
- package/dist/chunk-HOZDD6PW.js +2 -0
- package/dist/chunk-HRYYNBVC.js +3 -0
- package/dist/chunk-INDAJN42.js +94 -0
- package/dist/chunk-JMS5NTP7.js +3 -0
- package/dist/chunk-ME3X2KFY.js +14 -0
- package/dist/chunk-NE7SC2BX.js +2 -0
- package/dist/chunk-SCJNCGMF.js +17 -0
- package/dist/chunk-UDUICSME.js +1 -0
- package/dist/chunk-VGJ3V4QQ.js +78 -0
- package/dist/chunk-ZDNZCQUQ.js +2 -0
- package/dist/chunk-ZKK6E42X.js +1 -0
- package/dist/chunk-ZT6T2W4B.js +2 -0
- package/dist/cli.js +24 -0
- package/dist/environment-bake-5P4IAL4O.js +4 -0
- package/dist/index.d.ts +1183 -0
- package/dist/index.js +272 -0
- package/dist/shader-autowire-DCODBFMX.js +18 -0
- package/dist/shader-browser-65V22LLL.js +1 -0
- package/dist/shader-browser-JII6ZFCW.js +2 -0
- package/dist/shader-capture-server.d.ts +272 -0
- package/dist/shader-capture-server.js +19 -0
- package/dist/shader-config-4EXO5DKK.js +2 -0
- package/dist/shader-parity-QXJWR6OZ.js +1 -0
- package/dist/shader-parity-XPKQQK26.js +2 -0
- package/dist/shader-project-runner-GUR3LTYS.js +5 -0
- package/dist/shader-transform-CUkZn5Oa.d.ts +55 -0
- package/dist/shader-watch-QHTNTSZE.js +2 -0
- package/dist/shader-workflow-U4G565EB.js +2 -0
- package/dist/status-DV2BYZHR.js +2 -0
- package/dist/text-atlas-BHPSDU7C.js +2 -0
- package/dist/transform.cjs +1 -0
- package/dist/transform.d.ts +62 -0
- package/dist/transform.js +1 -0
- package/dist/webpack-loader.cjs +1 -0
- package/dist/webpack-loader.d.ts +17 -0
- package/dist/webpack-loader.js +1 -0
- package/fonts/OFL-1.1.txt +93 -0
- package/package.json +113 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @three-blocks/devtools
|
|
2
|
+
|
|
3
|
+
## 1.0.0-alpha.176.g8ff8a72e6369
|
|
4
|
+
|
|
5
|
+
- ci: keep alpha readiness release-scoped (`8ff8a72e6369`).
|
|
6
|
+
|
|
7
|
+
This changelog is generated from Changesets.
|
|
8
|
+
|
|
9
|
+
## 0.1.0
|
|
10
|
+
|
|
11
|
+
- Initial WebGPU shader precompilation and verification toolchain.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Required Notice: Copyright (c) 2025-2026 Three Blocks — https://threejs-blocks.com
|
|
2
|
+
Required Notice: AI/ML training and dataset use are not licensed; text-and-data-mining rights reserved (EU 2019/790 Art. 4(3)). See NOTICE.
|
|
3
|
+
|
|
4
|
+
# PolyForm Noncommercial License 1.0.0
|
|
5
|
+
|
|
6
|
+
<https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
7
|
+
|
|
8
|
+
## Acceptance
|
|
9
|
+
|
|
10
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
11
|
+
|
|
12
|
+
## Copyright License
|
|
13
|
+
|
|
14
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
|
|
15
|
+
|
|
16
|
+
## Distribution License
|
|
17
|
+
|
|
18
|
+
The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
|
|
19
|
+
|
|
20
|
+
## Notices
|
|
21
|
+
|
|
22
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
|
|
23
|
+
|
|
24
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
25
|
+
|
|
26
|
+
## Changes and New Works License
|
|
27
|
+
|
|
28
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
29
|
+
|
|
30
|
+
## Patent License
|
|
31
|
+
|
|
32
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
33
|
+
|
|
34
|
+
## Noncommercial Purposes
|
|
35
|
+
|
|
36
|
+
Any noncommercial purpose is a permitted purpose.
|
|
37
|
+
|
|
38
|
+
## Personal Uses
|
|
39
|
+
|
|
40
|
+
Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, is use for a permitted purpose.
|
|
41
|
+
|
|
42
|
+
## Noncommercial Organizations
|
|
43
|
+
|
|
44
|
+
Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution is use for a permitted purpose regardless of the source of funding or obligations resulting from the funding.
|
|
45
|
+
|
|
46
|
+
## Fair Use
|
|
47
|
+
|
|
48
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
49
|
+
|
|
50
|
+
## No Other Rights
|
|
51
|
+
|
|
52
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
53
|
+
|
|
54
|
+
## Patent Defense
|
|
55
|
+
|
|
56
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
57
|
+
|
|
58
|
+
## Violations
|
|
59
|
+
|
|
60
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
61
|
+
|
|
62
|
+
## No Liability
|
|
63
|
+
|
|
64
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
65
|
+
|
|
66
|
+
## Definitions
|
|
67
|
+
|
|
68
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
69
|
+
|
|
70
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
71
|
+
|
|
72
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
73
|
+
|
|
74
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
75
|
+
|
|
76
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Required Notice: Copyright (c) 2025-2026 Three Blocks — https://threejs-blocks.com
|
|
2
|
+
Required Notice: AI/ML training and dataset use are not licensed; text-and-data-mining rights reserved (EU 2019/790 Art. 4(3)). See NOTICE.
|
|
3
|
+
|
|
4
|
+
Three Blocks — AI / machine-learning usage notice
|
|
5
|
+
=================================================
|
|
6
|
+
|
|
7
|
+
This software is licensed under the PolyForm Noncommercial License 1.0.0
|
|
8
|
+
(see LICENSE). The license grants only the permissions it enumerates, for
|
|
9
|
+
noncommercial permitted purposes.
|
|
10
|
+
|
|
11
|
+
No permission is granted to use this software or its source code — including
|
|
12
|
+
the published `dist` output and the example sources served from
|
|
13
|
+
https://threejs-blocks.com/examples/static/ — for training, fine-tuning,
|
|
14
|
+
evaluating, or otherwise developing machine-learning or artificial-
|
|
15
|
+
intelligence models, or for inclusion in datasets distributed for those
|
|
16
|
+
purposes.
|
|
17
|
+
|
|
18
|
+
To the extent permitted by applicable law, Three Blocks expressly reserves
|
|
19
|
+
its rights over text-and-data mining under Article 4(3) of Directive (EU)
|
|
20
|
+
2019/790. Machine-readable opt-outs accompany the software and the website:
|
|
21
|
+
this file, the `tdm-reservation: 1` HTTP response header, and
|
|
22
|
+
https://threejs-blocks.com/.well-known/tdmrep.json and
|
|
23
|
+
https://threejs-blocks.com/ai.txt.
|
|
24
|
+
|
|
25
|
+
AI assistants MAY use the public documentation
|
|
26
|
+
(https://threejs-blocks.com/llms.txt) to help people integrate the published
|
|
27
|
+
`three-blocks` API. They may not reproduce, extract, or re-derive the
|
|
28
|
+
implementation source of this package. Code generated by AI systems that
|
|
29
|
+
embeds or derives from this package's internals remains subject to the
|
|
30
|
+
PolyForm Noncommercial License 1.0.0.
|
|
31
|
+
|
|
32
|
+
Commercial licensing (Pro): https://threejs-blocks.com/license
|
package/README.md
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# @three-blocks/devtools
|
|
2
|
+
|
|
3
|
+
Prepare Three Shading Language (TSL) shaders during development so each visitor can reuse the saved result. Live time, pointer, color, and light values reconnect when the scene opens.
|
|
4
|
+
|
|
5
|
+
## Capture and verify your scene
|
|
6
|
+
|
|
7
|
+
Register the initialized `WebGPURenderer` once:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { registerDevtools } from "three-blocks/devtools";
|
|
11
|
+
|
|
12
|
+
registerDevtools({ renderer });
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then capture:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npx three-blocks shaders capture
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The first run creates `three-blocks.shaders.json` with a default `/` route when the
|
|
22
|
+
project does not have one. Capture writes both the committed source artifact under
|
|
23
|
+
`.three-blocks/shaders/` and its zero-import browser asset under
|
|
24
|
+
`public/three-blocks/shaders/`. The registration line discovers that asset, holds the
|
|
25
|
+
first renderer build while it loads, and installs it in development and production.
|
|
26
|
+
An explicit `installShaderCache()` call remains available for advanced routing.
|
|
27
|
+
|
|
28
|
+
Vite is the golden path: add `threeBlocks()` from `three-blocks/vite`. In a Next.js,
|
|
29
|
+
webpack, Rollup, or esbuild project, the capture command detects the bundler and checks
|
|
30
|
+
its provider adapter. When wiring is missing, it prints the exact configuration diff
|
|
31
|
+
and asks before applying it. Use `--yes` only after reviewing that diff when running
|
|
32
|
+
non-interactively. The command starts a project-local Next.js server or builds and
|
|
33
|
+
serves `dist/`, `build/`, or `out/` automatically.
|
|
34
|
+
|
|
35
|
+
Use `--driver static --serve <dir>` for a nonstandard build directory, or `--url
|
|
36
|
+
<url>` to attach to a server you started. Explicit driver and URL choices never edit
|
|
37
|
+
bundler configuration.
|
|
38
|
+
|
|
39
|
+
The overlay changes from **Live** to **Precompiled** after a fresh capture loads. It shows the skipped TSL builds and the project-specific **TSL build time saved** when `timing.local.json` matches the current capture. Shader-relevant edits mark both the capture and its timing stale, so the app builds live until you capture again.
|
|
40
|
+
|
|
41
|
+
`WebGLRenderer` stays on live shader building. `WebGPURenderer` also uses the live path when it selects a WebGL fallback.
|
|
42
|
+
|
|
43
|
+
### Three.js r185 compatibility patch
|
|
44
|
+
|
|
45
|
+
Every adapter applies the same version-gated patch to `three/build/three.webgpu.js` in memory. It never writes `node_modules`. The r185 patch contains four independent changes:
|
|
46
|
+
|
|
47
|
+
- [#34068](https://github.com/mrdoob/three.js/pull/34068) adds the node-builder debug callback used by capture.
|
|
48
|
+
- [#34069](https://github.com/mrdoob/three.js/pull/34069) gives named node buffers deterministic labels.
|
|
49
|
+
- [#34070](https://github.com/mrdoob/three.js/pull/34070) adds the public node-builder state provider used by hydration.
|
|
50
|
+
- The local `compileAsync()` patch collects pipeline promises across one compile pass, yields after 8 ms work slices, then awaits the pipelines together. It captures each WebGPU error-scope promise before concurrent pipelines settle so the scopes remain balanced.
|
|
51
|
+
|
|
52
|
+
Each change has exact source anchors and fails closed on drift or partial application. Current captures require precompiled manifest version `3` and shader receipt transform version `3`; recapture older artifacts instead of editing them.
|
|
53
|
+
|
|
54
|
+
Delete an upstream backport when the supported Three.js release contains it. Reevaluate the local batching patch against each release. See [Maintain Three.js WebGPU compatibility](../../docs/maintenance/three-webgpu-release-compatibility.md) for markers, removal conditions, and verification.
|
|
55
|
+
|
|
56
|
+
### Manual bundler adapters
|
|
57
|
+
|
|
58
|
+
These are the manual equivalents of the diff that `shaders capture` offers.
|
|
59
|
+
|
|
60
|
+
esbuild:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
import { createEsbuildShaderPlugin } from "@three-blocks/devtools/transform";
|
|
64
|
+
|
|
65
|
+
await build({
|
|
66
|
+
// ...
|
|
67
|
+
plugins: [createEsbuildShaderPlugin({ root: process.cwd() })],
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Rollup:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
import { createRollupShaderPlugin } from "@three-blocks/devtools/transform";
|
|
75
|
+
|
|
76
|
+
export default {
|
|
77
|
+
// ...
|
|
78
|
+
plugins: [createRollupShaderPlugin({ root: process.cwd() })],
|
|
79
|
+
};
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
webpack:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
import { withThreeBlocksWebpack } from "@three-blocks/devtools/transform";
|
|
86
|
+
|
|
87
|
+
export default withThreeBlocksWebpack({
|
|
88
|
+
// ...
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Next.js:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import type { NextConfig } from "next";
|
|
96
|
+
import { withThreeBlocksNext } from "@three-blocks/devtools/transform";
|
|
97
|
+
|
|
98
|
+
const nextConfig: NextConfig = {
|
|
99
|
+
// Your existing webpack callback is composed, not replaced.
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export default withThreeBlocksNext(nextConfig);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The adapters always install the production provider hook. They add capture
|
|
106
|
+
instrumentation only when `THREE_BLOCKS_SHADER_TOOL=1`; a tool-managed build or server
|
|
107
|
+
sets that automatically. For a manually started webpack or Next.js server, set the
|
|
108
|
+
variable yourself and run `shaders capture --url http://localhost:3000`.
|
|
109
|
+
|
|
110
|
+
## Reference
|
|
111
|
+
|
|
112
|
+
The public command surface is `npx three-blocks`. This package also exposes the direct `three-blocks-devtools` binary for package-local and repository maintenance.
|
|
113
|
+
|
|
114
|
+
All commands support `--json` (stable machine output; human output stays line-oriented and
|
|
115
|
+
uncolored when piped). Static status validates `three-blocks.json`, committed shader
|
|
116
|
+
manifests, installed compatibility versions, the installed public `three-blocks/shaders`
|
|
117
|
+
runtime closure, and independently discovered shader-relevant source inputs. Runtime
|
|
118
|
+
evidence (worker, codecs, HMR) comes from the last `browser smoke` run and is reported as
|
|
119
|
+
a dated verification, never as live state.
|
|
120
|
+
|
|
121
|
+
### Precompile WebGPU shaders
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
three-blocks-devtools shaders status --check # no browser or GPU
|
|
125
|
+
three-blocks-devtools shaders capture --if-stale # isolated GPU context per scene
|
|
126
|
+
three-blocks-devtools shaders test --parity-only # one fast zero-build + pixel pair
|
|
127
|
+
three-blocks-devtools shaders test # parity + timing + published-page soak
|
|
128
|
+
three-blocks-devtools shaders test --skip-browser --mode strict
|
|
129
|
+
# CI freshness/schema gate
|
|
130
|
+
three-blocks-devtools shaders watch --debounce 250
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Projects may declare the complete capture matrix in `three-blocks.shaders.json`:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"schemaVersion": 1,
|
|
138
|
+
"scenes": [
|
|
139
|
+
{ "key": "default", "url": "/?scene=default" },
|
|
140
|
+
{ "key": "text", "url": "/?scene=text", "requiresText": true }
|
|
141
|
+
],
|
|
142
|
+
"settleFrames": 60,
|
|
143
|
+
"timeoutMs": 240000,
|
|
144
|
+
"viewport": { "width": 1024, "height": 640 },
|
|
145
|
+
"parity": { "frames": 90, "channelTolerance": 8, "maxDiffRatio": 0.01 },
|
|
146
|
+
"readiness": { "global": "__THREE_BLOCKS_READY__" },
|
|
147
|
+
"publicDir": "public",
|
|
148
|
+
"allowLiveBuilds": true
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Readiness is optional. Its global may be `true` or a promise; a selector is also
|
|
153
|
+
supported. With no override, the engine waits for its settled-frame and first-frame
|
|
154
|
+
contract and assumes nothing about application DOM.
|
|
155
|
+
|
|
156
|
+
This workflow is the main purpose of `@three-blocks/devtools`. Capture uses a version-gated r185 transform supplied by the selected bundler adapter. The transform journals real
|
|
157
|
+
render and compute `NodeBuilder` states, resolves stable keys through the public
|
|
158
|
+
`three-blocks/shaders` cache, exposes loopback readiness/telemetry, and uploads a typed payload.
|
|
159
|
+
The generated application owns no capture harness or patcher, and this tool never writes to
|
|
160
|
+
`node_modules`. A Three.js version or transform-anchor mismatch fails closed.
|
|
161
|
+
|
|
162
|
+
All configured scenes must pass before the tool replaces deterministic
|
|
163
|
+
`.three-blocks/shaders/<scene>.webgpu.ts` modules; `meta.json` is the last commit marker. It records
|
|
164
|
+
runtime/tool/schema versions, a `threeBlocksShaderClosure` hash, shader-relevant app-source hashes,
|
|
165
|
+
bytes, stage coverage, and skipped render/compute builds. App hashing begins at scene modules and
|
|
166
|
+
real shader registrations and follows only local runtime imports. Unrelated modules, type-only
|
|
167
|
+
imports, and DOM copy are not freshness inputs. Relevant source changes during capture abort the
|
|
168
|
+
commit. `watch` is explicitly opt-in and permits
|
|
169
|
+
only one running capture plus one coalesced rerun; failures preserve the prior committed receipt.
|
|
170
|
+
Explicit stable keys remain the clearest choice for complex, conditional capture matrices.
|
|
171
|
+
When an otherwise unregistered application or Three-internal build is first observed,
|
|
172
|
+
capture assigns it a deterministic scene-scoped key and records that automatic namespace
|
|
173
|
+
in the manifest. Set `allowLiveBuilds: false` when a project intentionally requires any
|
|
174
|
+
build that still cannot be addressed to fail capture.
|
|
175
|
+
|
|
176
|
+
`shaders test` first repeats the no-GPU matrix inspection. Its browser gate then proves that the
|
|
177
|
+
live baseline builds every registered render pipeline and compute kernel, while the fresh path
|
|
178
|
+
performs zero registered builds, covers render and compute injection independently, reports no
|
|
179
|
+
misses, reaches first-frame readiness, renders non-black output, and matches deterministic pixels.
|
|
180
|
+
Successful scenes are checkpointed immediately against their scene receipt and the shared
|
|
181
|
+
runtime/tool contract, so a later failure can resume at the missing scene. `--parity-only` runs
|
|
182
|
+
one live/precompiled pair without timing warmups, repeats, or the published-page soak. The default
|
|
183
|
+
mode retains those slower measurements and production-page checks. A parity observation that
|
|
184
|
+
returns no result is capped at 10 seconds.
|
|
185
|
+
On parity failure it writes live, precompiled, and diff PNGs under
|
|
186
|
+
`.three-blocks/shaders/parity/`.
|
|
187
|
+
|
|
188
|
+
### Verify a browser integration
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
three-blocks-devtools browser smoke --route / --json
|
|
192
|
+
three-blocks-devtools browser smoke --hmr src/offscreen/meshes/Scene.ts
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The smoke gate loads the project's real Vite config on an ephemeral loopback port. It requires
|
|
196
|
+
the visible OffscreenCanvas worker plus `workerReady`, `assetsReady`, and `compileEnd`; it also
|
|
197
|
+
requires `textReady` when the Vite text configuration is enabled. Every configured Draco and
|
|
198
|
+
KTX2 route is fetched, the lazy Meshopt decoder is initialized, page and console errors fail the
|
|
199
|
+
run, and both the WebGPU screenshot and readable 2D panels are checked for an all-black frame.
|
|
200
|
+
|
|
201
|
+
The command reads the starter's built-in readiness check. Application tutorials describe the visible **Starting**, **Ready**, **Precompiled**, and **Live** states instead of this maintainer contract. Contributors can inspect the exact protocol in the [maintainer browser-verification reference](../../docs/maintenance/browser-verification.md).
|
|
202
|
+
|
|
203
|
+
`--hmr <project-relative-module>` emits a synthetic watcher change through Vite for an already
|
|
204
|
+
loaded scene module. It runs the real HMR graph without writing or touching source and verifies
|
|
205
|
+
that the browser acknowledges the update while lifecycle readiness remains stable.
|
|
206
|
+
|
|
207
|
+
Only the two documented ambient diagnostics exported in `DOCUMENTED_BROWSER_NOISE` are filtered:
|
|
208
|
+
Three Inspector's invalid `extensions.json` response and Chromium's experimental WebGPU notice.
|
|
209
|
+
|
|
210
|
+
### Bake environment lighting
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
three-blocks-devtools environment bake --size 256
|
|
214
|
+
three-blocks-devtools environment bake --output src/assets/environment/studio.pmrem.ktx2 --json
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The browser entry renders Three.js `RoomEnvironment` through WebGPU and exports the PMREM CubeUV
|
|
218
|
+
atlas. Node validates RGBA16F topology, zstd-compresses at a deterministic level, decodes every
|
|
219
|
+
level byte-for-byte, records the final SHA-256 checksum, and transactionally replaces the KTX2
|
|
220
|
+
and JSON metadata pair. Size, time, upload, path, and file bounds are enforced. `--no-zstd` is an
|
|
221
|
+
explicit compatibility opt-out.
|
|
222
|
+
|
|
223
|
+
Both GPU commands accept `--root <path>` for integration workspaces that intentionally do
|
|
224
|
+
not carry generated-project metadata. Normal generated projects are discovered automatically.
|
|
225
|
+
|
|
226
|
+
### Ship it
|
|
227
|
+
|
|
228
|
+
Commit `.three-blocks/shaders/` and the generated public manifests, then add one
|
|
229
|
+
GPU-less CI command:
|
|
230
|
+
|
|
231
|
+
```sh
|
|
232
|
+
npx three-blocks shaders test --skip-browser --mode strict
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Use `--reporter json` for CI annotations. Run the full `shaders test` in an optional
|
|
236
|
+
WebGPU lane. Production selects the hydration-only `three-blocks/devtools` condition:
|
|
237
|
+
overlay and stats implementation bytes are absent, while the bounded
|
|
238
|
+
`three-blocks/shaders` runtime remains. Opt into its local production console receipt
|
|
239
|
+
with `threeBlocks({ stats: { production: true } })`; no telemetry leaves the app.
|
|
240
|
+
|
|
241
|
+
Text artifacts remain `missing` or `invalid` until configured glyph coverage, checksums,
|
|
242
|
+
orientation, and KTX2 decode round-trip validation succeed. No command performs account or
|
|
243
|
+
entitlement checks.
|
|
244
|
+
|
|
245
|
+
## License
|
|
246
|
+
|
|
247
|
+
Free for personal and noncommercial projects. Commercial projects are covered
|
|
248
|
+
by the Pro plan's lifetime license — each project you start while your plan is
|
|
249
|
+
active is licensed forever, for the versions released while it was active. No
|
|
250
|
+
runtime gating.
|
|
251
|
+
|
|
252
|
+
This package uses the [PolyForm Noncommercial 1.0.0 license](./LICENSE). Keep
|
|
253
|
+
the Required Notice when redistributing it; full commercial terms are at
|
|
254
|
+
[threejs-blocks.com/license](https://threejs-blocks.com/license).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as n from'three/webgpu';import {RoomEnvironment}from'three/addons/environments/RoomEnvironment.js';import {KTX2Exporter}from'three/addons/exporters/KTX2Exporter.js';var R=Object.defineProperty;var E=(e,o)=>R(e,"name",{value:o,configurable:true});function l(){let e=Number(new URLSearchParams(location.search).get("size")??256);if(!Number.isSafeInteger(e)||e<16||e>1024||(e&e-1)!==0)throw new Error(`RoomEnvironment cube size must be a power of two in 16...1024; received ${String(e)}.`);return e}E(l,"readCubeSize");async function _(){let e=document.querySelector("#three-blocks-environment-baker");if(!e)throw new Error("RoomEnvironment bake canvas is missing.");let o=l(),r=new n.WebGPURenderer({canvas:e,antialias:false}),t,a,i;try{await r.init(),t=new RoomEnvironment,a=new n.PMREMGenerator(r),i=a.fromScene(t,0,.1,100,{size:o});let m=await new KTX2Exporter().parse(r,i),s=await fetch("/__three-blocks/devtools/environment-bake/upload",{method:"POST",body:m,headers:{"content-type":"image/ktx2","x-three-revision":n.REVISION}});if(!s.ok)throw new Error(`RoomEnvironment upload failed: HTTP ${s.status} ${await s.text()}`);globalThis.__THREE_BLOCKS_ROOM_ENVIRONMENT_BAKE__={ok:!0};}finally{i?.dispose(),a?.dispose(),t?.dispose(),r.dispose();}}E(_,"bake");_().catch(e=>{let o=e instanceof Error?e.stack??e.message:String(e);globalThis.__THREE_BLOCKS_ROOM_ENVIRONMENT_BAKE__={ok:false,error:o},console.error(e);});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
interface ShaderCaptureReadiness {
|
|
2
|
+
readonly selector?: string;
|
|
3
|
+
readonly global?: string;
|
|
4
|
+
}
|
|
5
|
+
interface ShaderCaptureRuntimeConfiguration {
|
|
6
|
+
readonly capture: boolean;
|
|
7
|
+
readonly forceLive: boolean;
|
|
8
|
+
readonly settleFrames: number;
|
|
9
|
+
/** Maximum visible settle time after readiness before capture posts, regardless of late builds. */
|
|
10
|
+
readonly settleTimeoutMs?: number;
|
|
11
|
+
/** Pause the settle countdown while an interactive capture tab is hidden. */
|
|
12
|
+
readonly visibilityGuard?: boolean;
|
|
13
|
+
/** Overlay-capture session identity. Omitted by the driven browser capture. */
|
|
14
|
+
readonly captureId?: string;
|
|
15
|
+
/** Browser storage key cleared after a successful overlay capture POST. */
|
|
16
|
+
readonly sessionKey?: string;
|
|
17
|
+
/** Per-dev-server token sent as an HTTP header by overlay capture. */
|
|
18
|
+
readonly token?: string;
|
|
19
|
+
readonly readiness?: ShaderCaptureReadiness;
|
|
20
|
+
readonly transform: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Structural mirror of runtime `bindingKindOf`. The capture bundle is injected into
|
|
25
|
+
* `three.webgpu.js`, so importing the runtime value here would create a module cycle.
|
|
26
|
+
*/
|
|
27
|
+
declare function capturedBindingKind(value: object): string;
|
|
28
|
+
|
|
29
|
+
type UnknownRecord = Record<string, unknown>;
|
|
30
|
+
declare function configureThreeBlocksShaderCapture(next: ShaderCaptureRuntimeConfiguration): void;
|
|
31
|
+
declare function activeShaderCaptureScene(): string;
|
|
32
|
+
/**
|
|
33
|
+
* Capture-runtime copy of the devtools timing seam. This module is injected as a
|
|
34
|
+
* standalone browser script and therefore cannot import three-blocks/devtools.
|
|
35
|
+
*/
|
|
36
|
+
declare function wrapThreeBlocksCaptureTimedBuild(builder: UnknownRecord, key: 'build' | 'buildAsync', record?: (elapsedMs: number) => void, clock?: () => number, onBuilt?: () => void): void;
|
|
37
|
+
/** Called immediately after Three creates a live NodeBuilder, before setup/build. */
|
|
38
|
+
declare function instrumentThreeBlocksShaderBuilder(builderValue: unknown, rendererValue: unknown, targetValue?: unknown): void;
|
|
39
|
+
/** Called after the #34068 builder callback observes a successful real build. */
|
|
40
|
+
declare function recordThreeBlocksShaderBuild(builderValue: unknown, rendererValue: unknown): void;
|
|
41
|
+
/** Called at the top of r185 getForRender/getForCompute before provider lookup. */
|
|
42
|
+
declare function prepareThreeBlocksShaderRenderer(rendererValue: unknown, namespaceValue?: unknown, revisionValue?: unknown): void;
|
|
43
|
+
declare function pageLoadingIsComplete(root: UnknownRecord, readiness?: ShaderCaptureReadiness): boolean;
|
|
44
|
+
|
|
45
|
+
export { activeShaderCaptureScene, capturedBindingKind, configureThreeBlocksShaderCapture, instrumentThreeBlocksShaderBuilder, pageLoadingIsComplete, prepareThreeBlocksShaderRenderer, recordThreeBlocksShaderBuild, wrapThreeBlocksCaptureTimedBuild };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var Pt=Object.defineProperty;var l=(e,t)=>Pt(e,"name",{value:t,configurable:true});var Ae="three-webgpu-r185-v1",et=["fragmentNode","vertexNode","colorNode","positionNode","normalNode","opacityNode","alphaTestNode","backdropNode","backdropAlphaNode","emissiveNode","metalnessNode","roughnessNode","clearcoatNode","clearcoatRoughnessNode","transmissionNode","thicknessNode","iorNode","outputNode","mrtNode","depthNode","castShadowNode","receivedShadowNode","maskNode","envNode"];var z=["_renderContexts","_renderContexts"],P=Object.freeze({renderContextMrt:"three-r185-render-context-mrt",renderContextInput:"three-r185-render-context-input",skinningEvent:"three-r185-skinning-event",morphUpdateEvent:"three-r185-morph-update-event",maxMip:"three-r185-max-mip",morphTargetTexture:"three-r185-morph-target-texture"});function Te(e){let t=/^(.*)-([^-]+)-(-?\d+)$/u.exec(e);if(t?.[1]===void 0||t[2]===void 0||t[3]===void 0)return;let n=Number(t[3]);if(Number.isSafeInteger(n))return {attachmentState:t[1],mrtState:t[2],callDepth:n}}l(Te,"parseThreeR185RenderContextKey");function tt(e){return e==="185"||e===185}l(tt,"supportsThreeR185Revision");function Ot(e){let t=e.constructor;return (typeof t=="function"||typeof t=="object"&&t!==null)&&typeof Reflect.get(t,"name")=="string"?String(Reflect.get(t,"name")):"unknown"}l(Ot,"constructorName");function je(e){let t=e,n=l(i=>t[i]===true,"flag"),r=typeof t.textureNode=="object"&&t.textureNode!==null||typeof t.nodeUniform=="object"&&t.nodeUniform!==null;return n("isNodeUniformsGroup")?"NodeUniformsGroup":n("isUniformsGroup")?"UniformsGroup":n("isNodeUniformBuffer")?"NodeUniformBuffer":n("isUniformBuffer")?"UniformBuffer":n("isStorageBuffer")?r?"NodeStorageBuffer":"StorageBuffer":n("isSampledCubeTexture")?r?"NodeSampledCubeTexture":"SampledCubeTexture":n("isSampledTexture3D")?"NodeSampledTexture3D":n("isSampled3DTexture")?"Sampled3DTexture":n("isSampledArrayTexture")?r?"NodeSampledArrayTexture":"SampledArrayTexture":n("isSampledTexture")?r?"NodeSampledTexture":"SampledTexture":n("isSampler")?r?"NodeSampler":"Sampler":typeof t.kind=="string"?t.kind:Ot(e)}l(je,"capturedBindingKind");var nt="three-blocks.shader-capture.runtime.v1";var Ft=Symbol.for("three-blocks.shader-capture.cache.v1"),Dt=Symbol.for("three-blocks.shader-capture.cache-value.v1"),$e="/__three-blocks/shaders/capture",oe="/__three-blocks/shaders/telemetry",Re=4096,Kt=4,Ht=65536,zt=1e3,Gt=/^[a-z0-9][a-z0-9_-]{0,63}$/u,qt=new Set(["cameraProjectionMatrix","cameraProjectionMatrixInverse","cameraViewMatrix","cameraWorldMatrix","cameraNormalMatrix","cameraPosition"]),rt=["lightPosition","lightTargetPosition","lightViewPosition","lightShadowMatrix"],Wt=new Set(["_texture","_width","_height","_maxMip","_matrixUniform","_flipYUniform"]),Jt={bias:"shadowBias",intensity:"shadowIntensity",normalBias:"shadowNormalBias",radius:"shadowRadius",blurSamples:"shadowBlurSamples",mapSize:"shadowMapSize"},x={buildCalls:0,renderBuilds:0,computeBuilds:0,registeredBuilds:0,registeredRenderBuilds:0,registeredComputeBuilds:0,buildMs:0,injected:0,injectedRender:0,injectedCompute:0,missed:0,missedRender:0,missedCompute:0,missedKeys:[]},A={capture:false,forceLive:false,settleFrames:60,readiness:{},transform:1},St=new WeakMap,ot=new WeakSet,it=new WeakSet,Ue=new WeakMap,Pe=new Set,wt=new WeakMap,pe=[],ge=[],st=new WeakMap,at=new WeakMap,ct=new WeakMap,D,ce=0,Ce=false,se=false,K="default",J,Y,W=false,Oe=0,de,dt=false,B,_,me={},ne,re=false;function he(e){return /^.+\/input-[a-zA-Z0-9_-]+-\d{4}$/u.test(e)}l(he,"isAutomaticInputContainerKey");function p(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}l(p,"isRecord");function Le(e,t=new Set){if(e===null||typeof e!="object"||t.has(e))return;if(t.add(e),Array.isArray(e)){for(let r of e){let i=Le(r,t);if(i)return i}return}let n=e;for(let r of ["key","container"]){let i=n[r];if(typeof i=="string"&&he(i))return i}for(let r of Object.values(n)){let i=Le(r,t);if(i)return i}}l(Le,"automaticInputContainerReference");function Ie(e,t=new Set){if(e===null||typeof e!="object"||t.has(e))return;if(t.add(e),Array.isArray(e)){for(let s of e){let o=Ie(s,t);if(o)return o}return}let n=e,r=n.container,i=n.path;if(typeof r=="string"&&Array.isArray(i)){let s=i.filter(o=>typeof o=="string");if(r==="@renderer"&&s.includes(z[0])||r==="@object"&&s.includes("_renderer"))return `${r}.${s.join(".")}`}for(let s of Object.values(n)){let o=Ie(s,t);if(o)return o}}l(Ie,"transientRendererReference");function ye(e){return p(e)&&e.isNode===true}l(ye,"isNode");function N(e){if(p(e)&&typeof e.getSelf=="function"){let t=e.getSelf();return ye(t)?t:void 0}return ye(e)?e:void 0}l(N,"nodeFrom");function ut(e){let t=new Map;if(e.isNode!==true)return t;t.set(e,[]);let n=[e];for(let r=0;r<n.length;r++){let i=n[r];if(!i||typeof i.getSerializeChildren!="function")continue;let s=t.get(i)??[],o=0;for(let c of i.getSerializeChildren()){let a=N(c.childNode);if(a&&!t.has(a)&&(t.set(a,[...s,o]),n.push(a)),o++,o>Re)throw new Error("Shader node graph exceeds the capture child limit.")}}return t}l(ut,"indexNodeGraph");function Nt(e){if(e.k==="owned"){let t=Nt(e.owner);return t===e.owner?e:{...e,owner:t}}if(e.k==="container"&&e.key==="@renderer"&&e.path.length>=4&&e.path[0]===z[0]&&e.path[1]===z[1]&&e.path.at(-1)==="mrt"){let t=e.path[2],n=typeof t=="string"?Te(t):void 0;if(n!==void 0){let r=At(n.attachmentState);return {k:"recipe",id:P.renderContextMrt,version:1,input:{attachmentState:n.attachmentState,callDepth:n.callDepth,...r===void 0?{}:{samples:r}}}}}return e}l(Nt,"stableRenderContextAddress");function At(e){let t=e.split(":");if(t.length!==6)return;let n=Number(t[3]);return Number.isSafeInteger(n)&&n>=0?n:void 0}l(At,"renderAttachmentSamples");function Yt(e,t){let n=p(e)?e:{},r={isDepthTexture:n.isDepthTexture===true,isRenderTargetTexture:n.isRenderTargetTexture===true,isDataTexture:n.isDataTexture===true,isData3DTexture:n.isData3DTexture===true,isCubeTexture:n.isCubeTexture===true,format:typeof n.format=="number"?n.format:null,type:typeof n.type=="number"?n.type:null,compareFunction:typeof n.compareFunction=="number"?n.compareFunction:null};typeof n.name=="string"&&n.name.length>0&&(r.name=n.name),typeof n.colorSpace=="string"&&n.colorSpace.length>0&&(r.colorSpace=n.colorSpace);let i=At(t);return i!==void 0&&(r.samples=i),r}l(Yt,"textureResourceSignature");function Xt(e,t){if(e.k!=="inputNode"||e.value.container!=="@renderer")return e;let n=e.value.path;if(n.length<4||n[0]!==z[0]||n[1]!==z[1]||typeof n[2]!="string")return e;let r=Te(n[2]);if(r===void 0)return e;let i=n[3]==="depthTexture"&&n.length===4?"depthTexture":n[3]==="textures"&&n.length===5&&Number.isSafeInteger(n[4])?"texture":void 0;if(i===void 0)return e;let{k:s,value:o,...c}=e;return {k:"recipe",id:P.renderContextInput,version:1,input:{attachmentState:r.attachmentState,callDepth:r.callDepth,mrt:r.mrtState!=="default",resource:i,...i==="texture"?{index:Number(n[4])}:{},texture:Yt(t,r.attachmentState),node:c}}}l(Xt,"stableRenderContextInputAddress");function R(e){if(!p(e))return typeof e;let t=e.constructor;return (typeof t=="function"||p(t))&&typeof t.name=="string"?t.name:"unknown"}l(R,"constructorName");function ft(e){if(!p(e))return R(e);let t=p(e.image)?e.image:void 0;return [R(e),typeof e.uuid=="string"?`uuid=${e.uuid}`:"",typeof e.name=="string"&&e.name?`name=${e.name}`:"",e.isRenderTargetTexture===true?"renderTarget":"",e.isPMREMTexture===true?"pmrem":"",t&&typeof t.width=="number"&&typeof t.height=="number"?`${t.width}x${t.height}`:"",typeof e.format=="number"?`format=${e.format}`:"",typeof e.type=="number"?`type=${e.type}`:""].filter(Boolean).join("/")}l(ft,"textureLabel");function ue(e,t){return typeof e=="string"&&e.length>0?e.slice(0,512):t}l(ue,"boundedLabel");function Zt(){return typeof performance=="object"&&typeof performance.now=="function"?performance.now():Date.now()}l(Zt,"now");function Tt(e){return p(e)&&typeof e.then=="function"}l(Tt,"promiseLike");function Qt(e){A={capture:e.capture===true,forceLive:e.forceLive===true,settleFrames:Number.isSafeInteger(e.settleFrames)&&e.settleFrames>=0?e.settleFrames:60,settleTimeoutMs:Number.isSafeInteger(e.settleTimeoutMs)&&Number(e.settleTimeoutMs)>=1e3?Number(e.settleTimeoutMs):3e4,visibilityGuard:e.visibilityGuard===true,...typeof e.captureId=="string"?{captureId:e.captureId}:{},...typeof e.sessionKey=="string"?{sessionKey:e.sessionKey}:{},...typeof e.token=="string"?{token:e.token}:{},readiness:{...typeof e.readiness?.selector=="string"?{selector:e.readiness.selector}:{},...typeof e.readiness?.global=="string"?{global:e.readiness.global}:{}},transform:e.transform},ne=void 0,re=false,J=void 0,Y=void 0,W=false,Oe=0,de=void 0,_=void 0,Reflect.set(globalThis,Ft,n=>{p(n)&<(n);});let t=Reflect.get(globalThis,Dt);p(t)&<(t),(A.capture||jt())&&en();}l(Qt,"configureThreeBlocksShaderCapture");function jt(){let e=Reflect.get(globalThis,"location"),t=p(e)?Reflect.get(e,"search"):void 0;if(typeof t!="string")return false;let n=new URLSearchParams(t),r=n.get("threeBlocksShaderMode");return n.get("capture")==="1"||r==="live"||r==="precompiled"}l(jt,"drivenShaderSession");function He(){return A.capture||A.forceLive||jt()}l(He,"shaderSessionActive");function lt(e){if(B=e,!A.capture)return;let t=Ct(),n=e.automaticRegistrationPrefix,r=typeof n=="function"?Reflect.apply(n,e,[t]):void 0;typeof r=="string"&&(_=r);}l(lt,"adoptCaptureCache");function Vt(e){if(!A.capture||B===void 0)return;let t=B.automaticRegistrationPrefix,n=typeof t=="function"?Reflect.apply(t,B,[e]):void 0;if(typeof n=="string"){_=n;return}let r=B.enableAutomaticRegistration;if(typeof r=="function"){_="auto";try{Reflect.apply(r,B,[{scene:e,prefix:_}]);}catch(i){throw _=void 0,i}}}l(Vt,"ensureCaptureAutomaticRegistration");function en(){if(dt)return;let e=globalThis,t=e.requestAnimationFrame;if(typeof t!="function")return;dt=true;let n=0,r=0,i=false,s=new Map,o=l(()=>{i||s.size===0||(i=true,Reflect.apply(t,e,[()=>{i=false;let c=[...s.values()];s.clear();let a=n++*(1e3/60);for(let d of c)try{d(a);}catch(u){queueMicrotask(()=>{throw u});}o();}]));},"schedule");Reflect.set(e,"requestAnimationFrame",c=>{let a=++r;return s.set(a,c),o(),a}),Reflect.set(e,"cancelAnimationFrame",c=>{s.delete(c);});}l(en,"installDeterministicRaf");function I(e,t){if(!B)return;let n=B[e];return typeof n=="function"?Reflect.apply(n,B,t):void 0}l(I,"cacheCall");function Ct(){if(B&&typeof B.activeScene=="string"&&B.activeScene!=="default")return B.activeScene;let e=Reflect.get(globalThis,"location"),t=p(e)?Reflect.get(e,"search"):void 0,n=typeof t=="string"?new URLSearchParams(t).get("captureId"):null;return n!==null&&Gt.test(n)?n:B&&typeof B.activeScene=="string"?B.activeScene:"default"}l(Ct,"activeShaderCaptureScene");function X(){return Ct()}l(X,"activeScene");function ae(e,t,n,r){let i=I(e==="compute"?"registrationForCompute":"registrationForRender",e==="compute"?[t,n]:[t,n,r]);return (!p(i)||typeof i.key!="string")&&(Vt(n),i=I(e==="compute"?"registrationForCompute":"registrationForRender",e==="compute"?[t,n]:[t,n,r])),p(i)&&typeof i.key=="string"?i:void 0}l(ae,"sceneRegistration");function tn(e){return e.key}l(tn,"capturedRegistrationKey");function ze(e,t){let n=t==="compute"?e.object:e.material;return n!==null&&typeof n=="object"?n:void 0}l(ze,"builderTarget");function xt(e){return e.material===null||e.material===void 0?"compute":"render"}l(xt,"buildKind");function xe(e){if(!p(e))return;let t={};for(let n of ["uuid","id","name","type"]){let r=e[n];typeof r=="string"?t[n]=ue(r,""):(typeof r=="number"&&Number.isFinite(r)||typeof r=="boolean")&&(t[n]=r);}return Object.keys(t).length===0?void 0:t}l(xe,"objectIdentity");function nn(e,t,n,r){if(ge.length>=Re)return;let i=e==="compute"?t.object:t.material,s=ue(p(i)?i.name??i.type:void 0,"unknown"),o=I("registrations",[n]),c=xe(i),a=p(r)?xe(r.material):void 0;ge.push({kind:e,name:s,reason:e==="compute"?`unregistered compute "${s}"`:`unregistered material "${s}"`,...c===void 0?{}:{target:c},...a===void 0?{}:{renderObjectMaterial:a},...Array.isArray(o)?{registrations:o.slice(0,16).flatMap(d=>{if(!p(d))return [];let u=xe(d.target);return [{...typeof d.key=="string"?{key:ue(d.key,"")}:{},...typeof d.kind=="string"?{kind:ue(d.kind,"")}:{},...u??{},sameTarget:d.target===i,...p(r)?{sameRenderObjectMaterial:d.target===r.material}:{}}]})}:{}});}l(nn,"addSkipped");function pt(e,t,n=s=>{x.buildMs+=s;},r=Zt,i){let s=e[t];typeof s=="function"&&Reflect.set(e,t,l(function(...c){let a=r(),d;try{d=Reflect.apply(s,this,c);}catch(u){throw n(r()-a),u}return Tt(d)?Promise.resolve(d).then(u=>(n(r()-a),i?.(),u),u=>{throw n(r()-a),u}):(n(r()-a),i?.(),d)},"timedBuild"));}l(pt,"wrapThreeBlocksCaptureTimedBuild");function vt(e,t,n){if(!He()||!p(e)||!p(t)||ot.has(e))return;ot.add(e);let r=X(),i=I("containers",[r]);Ue.set(e,new Set(Array.isArray(i)?i.filter(b=>p(b)&&typeof b.key=="string").map(b=>String(b.key)):[]));let s=p(n)&&p(n.material)?n:void 0,o=s?"render":xt(e),c=o==="render"&&s?be("render",s):ze(e,o);c&&(s&&wt.set(e,s),ae(o,c,X(),s));let a=[];St.set(e,a);let d=e.getUniformFromNode;typeof d=="function"&&Reflect.set(e,"getUniformFromNode",l(function(j,g,f,m){let y=Reflect.apply(d,this,[j,g,f,m]),k=N(j),S=typeof f=="string"?f:this.shaderStage;if(k&&typeof g=="string"&&(S==="vertex"||S==="fragment"||S==="compute")){let v=p(y)&&typeof y.name=="string"?y.name:typeof m=="string"?m:null;a.push({node:k,type:g,stage:S,name:v,...typeof k.id=="number"?{nid:k.id}:{}});}return y},"captureUniform"));let u=l(()=>{it.has(e)||(it.add(e),Bt(e,t));},"recordBuild");pt(e,"build",void 0,void 0,u),pt(e,"buildAsync",void 0,void 0,u);}l(vt,"instrumentThreeBlocksShaderBuilder");function te(e){return Object.assign(Object.create(Object.getPrototypeOf(e)),e)}l(te,"cloneCaptureRecord");function rn(e){let t=Object.create(e);for(let o of ["object","material","scene","camera","lightsNode","context","vertexShader","fragmentShader","computeShader","observer","hardwareClipping","updateNodes","updateBeforeNodes","updateAfterNodes"]){let c=e[o];Reflect.set(t,o,o==="material"&&p(c)?te(c):Array.isArray(c)?[...c]:c);}let n=typeof e.getAttributesArray=="function"?Reflect.apply(e.getAttributesArray,e,[]):[],r=Array.isArray(n)?n.map(o=>p(o)?te(o):o):[];Reflect.set(t,"getAttributesArray",()=>r);let i=typeof e.getBindings=="function"?Reflect.apply(e.getBindings,e,[]):[],s=Array.isArray(i)?i.map(o=>{if(!p(o))return o;let c=te(o),a=Array.isArray(o.bindings)?o.bindings.map(d=>{if(!p(d))return d;let u=te(d);return Array.isArray(d.uniforms)&&Reflect.set(u,"uniforms",d.uniforms.map(b=>p(b)?te(b):b)),u}):[];return Reflect.set(c,"bindings",a),c}):[];return Reflect.set(t,"getBindings",()=>s),t}l(rn,"snapshotBuilderState");function Bt(e,t){if(!He()||A.capture&&se||!p(e)||!p(t))return;x.buildCalls++,Y=Date.now(),W=false;let n=xt(e);n==="compute"?x.computeBuilds++:x.renderBuilds++;let r=X();K=r;let i=Ue.get(e)??new Set,s=I("containers",[r]);if(Array.isArray(s))for(let d of s)p(d)&&typeof d.key=="string"&&he(d.key)&&!i.has(d.key)&&Pe.add(d.key);Ue.delete(e);let o=ze(e,n),c=n==="render"?wt.get(e)??(p(e.object)?e.object:void 0):void 0,a=o?ae(n,o,r,c):void 0;if(a){x.registeredBuilds++,n==="compute"?x.registeredComputeBuilds++:x.registeredRenderBuilds++;let d=tn(a);if(pe.length<Re){let u=rn(e),b={scene:r,key:d,kind:n,builder:u,renderer:t,...c?{renderObject:c}:{},journal:[...St.get(e)??[]]};pe.push(b);}}else nn(n,e,r,c);Et();}l(Bt,"recordThreeBlocksShaderBuild");function be(e,t){return e==="compute"?t!==null&&typeof t=="object"?t:void 0:p(t)&&t.material!==null&&typeof t.material=="object"?t.material:void 0}l(be,"targetForProvider");function gt(e,t,n){if(A.capture&&se)return;let r=X();K=r;let i=be(e,t),s=e==="render"&&p(t)?t:void 0,o=i?ae(e,i,r,s):void 0;n!=null?(x.injected++,e==="compute"?x.injectedCompute++:x.injectedRender++):o&&(x.missed++,e==="compute"?x.missedCompute++:x.missedRender++,x.missedKeys.length<Re&&!x.missedKeys.includes(o.key)&&x.missedKeys.push(o.key)),A.capture||Et();}l(gt,"recordProviderResult");function on(e){let t=e.debug;if(!p(t))return;let n=t.onNodeBuilderCreated,r=ct.get(e);if(n===r)return;let i=typeof n=="function"?n:void 0,s=l(function(c,a){i!==void 0&&Reflect.apply(i,this,[c,a]),vt(c,e,a);},"captureNodeBuilder");ct.set(e,s),t.onNodeBuilderCreated=s;}l(on,"installCaptureBuilderCallback");function sn(e,t,n){if(!p(e))return;if(n!==void 0&&!tt(n))throw new Error(`@three-blocks/devtools supports Three.js 0.185.x capture; received revision ${JSON.stringify(n)}.`);if(!He())return;if(p(t)&&t!==me&&(me=t,fe=void 0),on(e),A.forceLive){let a=at.get(e);a||(a={__threeBlocksCaptureForceLive:true,getForRender(d){let u=be("render",d);u&&ae("render",u,X(),p(d)?d:void 0);},getForCompute(d){let u=be("compute",d);u&&ae("compute",u,X());}},at.set(e,a)),e.nodeBuilderStateProvider=a;return}let r=e.nodeBuilderStateProvider;if(!p(r))return;let i=st.get(r);if(i){e.nodeBuilderStateProvider=i;return}if(r.__threeBlocksCaptureWrapper===true)return;let s=r.getForRender,o=r.getForCompute;if(typeof s!="function"||typeof o!="function")return;let c={__threeBlocksCaptureWrapper:true,getForRender(a,d){let u=Reflect.apply(s,r,[a,d]);return gt("render",a,u),u},getForCompute(a,d){let u=Reflect.apply(o,r,[a,d]);return gt("compute",a,u),u}};st.set(r,c),e.nodeBuilderStateProvider=c;}l(sn,"prepareThreeBlocksShaderRenderer");var an=Object.freeze({configureThreeBlocksShaderCapture:Qt,instrumentThreeBlocksShaderBuilder:vt,prepareThreeBlocksShaderRenderer:sn,recordThreeBlocksShaderBuild:Bt});Reflect.set(globalThis,Symbol.for(nt),an);function cn(e){return N(e)}l(cn,"unwrapTsl");var fe;function L(){if(fe)return fe;let e=new Map;for(let[t,n]of Object.entries(me)){let r=cn(n);r&&!e.has(r)&&e.set(r,t);}return fe=e,e}l(L,"tslMap");function dn(e,t){if(!(!t||!p(e._nodes)||typeof e._nodes.getEnvironmentNode!="function"))return N(Reflect.apply(e._nodes.getEnvironmentNode,e._nodes,[t]))}l(dn,"sceneEnvironmentNode");var mt=new WeakMap;function un(e,t,n){let r=Reflect.get(e,"getLightNodes");if(typeof r!="function")return [];let i=Reflect.get(t,"getDataFromNode");if(typeof i=="function"){let c=Reflect.apply(i,t,[e]),a=p(c)?c.lightNodes:void 0;if(Array.isArray(a))return a.map(N).filter(d=>d!==void 0)}let o=Reflect.apply(r,e,[{renderer:n,context:{materialLightings:[]},getDataFromNode(c){let a=mt.get(c);return a||(a={},mt.set(c,a)),a}}]);return Array.isArray(o)?o.map(N).filter(c=>c!==void 0):[]}l(un,"lightNodes");function ht(e,t){let n=Reflect.get(me,e);return typeof n=="function"?N(Reflect.apply(n,void 0,[t])):void 0}l(ht,"lightUniform");function ve(e){if(!e)return [];let t=[],n=Reflect.get(e,"traverse");return typeof n=="function"&&Reflect.apply(n,e,[r=>{r!==null&&typeof r=="object"&&Reflect.get(r,"isLight")===true&&t.push(r);}]),t}l(ve,"sceneLights");function fn(e){if(!e)return [];let t=[],n=Reflect.get(e,"traverse");return typeof n=="function"&&Reflect.apply(n,e,[r=>{r!==null&&typeof r=="object"&&t.push(r);}]),t}l(fn,"sceneObjects");function ln(e){return !(Reflect.get(e,"isNode")===true||Reflect.get(e,"isObject3D")===true||Reflect.get(e,"isTexture")===true||Reflect.get(e,"isMaterial")===true||ArrayBuffer.isView(e)||e instanceof ArrayBuffer||e instanceof Set||e instanceof Promise)}l(ln,"isScannable");function pn(e,t,n,r=()=>false,i=false){let s=new Set,o=[{value:e,path:[],depth:0}];for(let c=0;c<o.length;c++){let a=o[c];if(!a||s.has(a.value)||a.depth>Kt)continue;let{value:d,path:u,depth:b}=a;s.add(d);let j=Array.isArray(d)?Array.from(d,(g,f)=>[f,g]):d instanceof Map?[...d.entries()].filter(g=>typeof g[0]=="string"||typeof g[0]=="number").map(([g,f])=>[`map:${String(g)}`,f]):Object.keys(d).map(g=>[g,Reflect.get(d,g)]);for(let[g,f]of j){if(f===null||typeof f!="object")continue;let m=[...u,g];if(!r(m))if(ye(f)){let y=N(f);y&&t(y,m),i&&o.push({value:y??f,path:m,depth:b+1});}else n(f,m),ln(f)&&o.push({value:f,path:m,depth:b+1});}}}l(pn,"scanContainer");function gn(e){if(new Uint8Array(new Uint16Array([258]).buffer)[0]!==2)throw new Error("Shader capture requires a little-endian host.");let t=new Uint8Array(e.buffer,e.byteOffset,e.byteLength),n=t.toBase64;if(typeof n=="function")return n.call(t);let r="",i=32768;for(let s=0;s<t.length;s+=i)r+=String.fromCharCode(...t.subarray(s,s+i));return btoa(r)}l(gn,"bytesToBase64");function yt(e){if(typeof e=="number"&&Number.isFinite(e)||typeof e=="boolean")return e;if(p(e)){for(let[t,n]of [["isVector2","v2"],["isVector3","v3"],["isVector4","v4"],["isColor","c"],["isMatrix3","m3"],["isMatrix4","m4"]])if(e[t]===true&&typeof e.toArray=="function"){let r=Reflect.apply(e.toArray,e,[]);if(Array.isArray(r)&&r.every(i=>typeof i=="number"&&Number.isFinite(i)))return {t:n,a:r}}}}l(yt,"serializeValueItem");function bt(e){if(Array.isArray(e)){let r=e.map(yt);return r.every(i=>i!==void 0)?{t:"arr",items:r}:void 0}let t=yt(e);if(t!==void 0)return t;if(p(e)&&e.isTexture===true&&e.image==null&&e.isRenderTargetTexture!==true&&e.version===0&&(e.name===""||e.name===void 0))return {t:"tex"};if(!p(e)||e.isDataTexture!==true||!p(e.image))return;let n=e.image.data;if(!(!ArrayBuffer.isView(n)||typeof Reflect.get(n,"length")!="number"||Number(Reflect.get(n,"length"))>Ht))return {t:"dtex",arrayType:R(n),data:gn(n),width:typeof e.image.width=="number"?e.image.width:0,height:typeof e.image.height=="number"?e.image.height:0,format:typeof e.format=="number"?e.format:0,type:typeof e.type=="number"?e.type:0,minFilter:typeof e.minFilter=="number"?e.minFilter:0,magFilter:typeof e.magFilter=="number"?e.magFilter:0,wrapS:typeof e.wrapS=="number"?e.wrapS:0,wrapT:typeof e.wrapT=="number"?e.wrapT:0,name:typeof e.name=="string"?e.name:""}}l(bt,"serializeStaticValue");function mn(e){if(!(Object.hasOwn(e,"update")||Object.hasOwn(e,"updateBefore")||Object.hasOwn(e,"updateAfter"))){if(Reflect.get(e,"isStorageTextureNode")===true)return "storageTexture";if(Reflect.get(e,"isStorageBufferNode")===true)return "storage";switch(R(e)){case "BufferNode":return "buffer";case "BufferAttributeNode":return "bufferAttribute";case "Texture3DNode":return "texture3D";case "CubeTextureNode":return "cubeTexture";case "TextureNode":return "texture";case "UniformArrayNode":return "uniformArray";case "UniformNode":return "uniform";case "PMREMNode":return "pmremTexture";default:return}}}l(mn,"inputClass");function Rt(e,t){let n=R(e);return n!==R(t)||["TextureNode","Texture3DNode","CubeTextureNode"].includes(n)||!!N(Reflect.get(e,"compareNode"))!=!!N(Reflect.get(t,"compareNode"))||Reflect.get(e,"access")!==Reflect.get(t,"access")?false:R(e)==="BufferAttributeNode"?["bufferType","bufferStride","bufferOffset","usage","instanced"].every(r=>Reflect.get(e,r)===Reflect.get(t,r)):true}l(Rt,"hasEquivalentSharedInputShape");function hn(e){if(e.k==="inputNode")return e.value;if(e.k==="container")return {container:e.key,path:[...e.path,"value"]};if(e.k==="anchor"&&e.path.length===0)return {container:"@material",path:[e.slot,"value"]}}l(hn,"sharedTextureValueLocation");function yn(e){if(e?.k==="container")return {container:e.key,path:e.path};if(e?.k==="anchor"&&e.path.length===0)return {container:"@material",path:[e.slot]}}l(yn,"sharedTextureNodeLocation");function kt(e,t){if(e.isDataArrayTexture!==true||e.format!==1023||e.type!==1015||!p(e.image)||e.image.data===null||typeof e.image.data!="object"||R(e.image.data)!=="Float32Array")return false;let n=t.morphAttributes,r=t.attributes;if(!p(n)||!p(r)||!p(r.position))return false;let i=Array.isArray(n.position)?n.position:[],s=Array.isArray(n.normal)?n.normal:[],o=Array.isArray(n.color)?n.color:[],c=i.length>0?i:s.length>0?s:o;if(c.length===0)return false;let a=r.position.count;if(!Number.isSafeInteger(a)||Number(a)<0)return false;let d=o.length>0?3:s.length>0?2:1,u=Number(a)*d,b=1;return u>4096&&(b=Math.ceil(u/4096),u=4096),e.image.width===u&&e.image.height===b&&e.image.depth===c.length&&Reflect.get(e.image.data,"length")===u*b*4*c.length}l(kt,"isThreeR185MorphTargetTexture");function Fe(e,t=new Set){if(e===null||typeof e!="object"||t.has(e))return false;if(t.add(e),Array.isArray(e))return e.some(r=>Fe(r,t));let n=e;return n.k==="recipe"?true:Object.values(n).some(r=>Fe(r,t))}l(Fe,"addressUsesRecipe");var De=class{static{l(this,"RecipeCollisionIndex");}#t=new Map;register(t,n,r,i){if(!Fe(t)||t.k==="recipe"&&t.id===P.skinningEvent)return;let s=JSON.stringify(t),o=this.#t.get(s);if(o!==void 0&&o.source!==n)throw new Error(`Shader recipe collision between "${o.shaderKey}" (${o.usage}) and "${r}" (${i}) for ${s}. Register the live resources in distinct stable application containers or make their structural recipe signatures unique.`);o===void 0&&this.#t.set(s,{source:n,shaderKey:r,usage:i});}};function G(e){return e.includes("_inspector")||e.includes("_renderer")||e.includes("_lastRenderer")||e.includes("renderer")||e.some(t=>typeof t=="string"&&t.startsWith("_cached"))}l(G,"applicationContainerPathIsTransient");var Ke=class{static{l(this,"CaptureClassifier");}#t;#a;#e=new Map;#c=new Map;#n=new Map;#d=new Map;#o=[];#s=[];#l=0;constructor(t,n){this.#t=t,this.#a=n;let r=t.kind==="compute"?ye(t.target)?[{slot:"compute",node:t.target}]:[]:et.flatMap(g=>{let f=N(Reflect.get(t.target,g));return f?[{slot:g,node:f}]:[]});for(let g of r)this.#r(g.node,{k:"anchor",key:t.key,slot:g.slot,path:[]});let i=N(t.builder.lightsNode);this.#s.length=0;let s=this.#s;if(i){let g=un(i,t.builder,t.renderer);this.#o.push(`lights=${g.length}`);for(let f=0;f<g.length;f++){let m=g[f];if(!m)continue;let y={k:"lightNode",light:f};this.#r(m,y);let k=Reflect.get(m,"light");if(Reflect.get(m,"isAnalyticLightNode")===true){let S=N(Reflect.get(m,"baseColorNode")),v=S??N(Reflect.get(m,"colorNode"));v&&this.#e.set(v,{k:"owned",owner:y,path:[S!==void 0||k!==null&&typeof k=="object"&&Reflect.get(k,"castShadow")===true?"baseColorNode":"colorNode"]});}if(k!==null&&typeof k=="object")for(let S of rt){s[f]=k;let v=ht(S,k);this.#o.push(`${f}/${S}=${v?`${R(v)}:${R(Reflect.get(v,"value"))}:${String(Reflect.get(v,"updateType"))}`:"missing"}`),v&&this.#r(v,{k:"lightUniform",fn:S,light:f});}}}else this.#o.push("lights=missing");let o=t.builder.scene!==null&&typeof t.builder.scene=="object"?t.builder.scene:null;for(let[g,f]of ve(o).entries()){if(s.includes(f))continue;let m=s.length+g;for(let y of rt){let k=ht(y,f);k&&this.#r(k,{k:"lightUniform",fn:y,light:m,sceneLight:g});}}let c=dn(t.renderer,o);c&&this.#r(c,{k:"sceneEnv"});let a=l((g,f,m,y=false)=>{this.#n.has(f)||this.#n.set(f,{container:g,path:[]}),pn(f,(k,S)=>this.#r(k,{k:"container",key:g,path:S}),(k,S)=>{this.#n.has(k)||this.#n.set(k,{container:g,path:S});},m,y);},"scan");if(t.kind==="render")for(let g of Object.getOwnPropertyNames(t.target)){let f=N(Reflect.get(t.target,g));f&&!this.#e.has(f)&&this.#e.set(f,{k:"container",key:"@material",path:[g]});}let d=I("containers",[t.scene]),u=Array.isArray(d)?d.find(g=>p(g)&&typeof g.key=="string"&&g.key.includes("/resource-batched-text-")):void 0;if(p(u)&&typeof u.key=="string"&&u.target!==null&&typeof u.target=="object"&&a(u.key,u.target,G,true),Array.isArray(d)){for(let g of d)if(g!==u&&p(g)&&typeof g.key=="string"&&g.target!==null&&typeof g.target=="object"){let f=g.key;if(he(f)||Pe.has(f))continue;a(f,g.target,G,true);}}if(t.kind==="render"){a("@material",t.target,k=>k.some(S=>typeof S=="string"&&S.startsWith("_")),true),t.renderObject&&a("@renderObject",t.renderObject,k=>k.length===1&&k[0]!=="context");let g=Reflect.get(t.renderer,"getMRT"),f=Reflect.get(t.builder,"context"),y=(p(f)?N(f.mrt):void 0)??(typeof g=="function"?N(Reflect.apply(g,t.renderer,[])):void 0);t.renderObject&&y&&this.#r(y,{k:"container",key:"@renderObject",path:["context","mrt"]});}let b=t.builder.object;b!==null&&typeof b=="object"&&a("@object",b,g=>G(g)||t.kind==="compute"&&g.some(f=>typeof f=="string"&&f.startsWith("_")),t.kind==="compute"),o&&a("@scene",o,G);for(let[g,f]of fn(o).entries())a(`@sceneObject:${g}`,f,G);a("@renderer",t.renderer,g=>g.length>=1&&g[0]==="_inspector"||g.length===2&&g[0]==="_nodes"&&g[1]==="nodeBuilderCache");let j=I("containers",[t.scene]);if(Array.isArray(j)){for(let g of j)if(p(g)&&typeof g.key=="string"&&g.target!==null&&typeof g.target=="object"){let f=g.key;if(he(f)||Pe.has(f))continue;a(f,g.target,G,true);}}}#i(t,n,r,i){let s=Reflect.get(t,"value"),o=this.#c.get(t)??i??(r.k==="recipe"&&r.id===P.renderContextInput&&s!==null&&typeof s=="object"?s:t);return this.#c.set(t,o),this.#a.register(r,o,this.#t.key,n),r}#r(t,n){!this.#e.has(t)&&!L().has(t)&&this.#e.set(t,n);for(let[r,i]of ut(t))r===t||this.#e.has(r)||L().has(r)||this.#e.set(r,{k:"owned",owner:n,path:i});}#u(t){if(R(t)!=="ReferenceNode")return;let n=Reflect.get(t,"property"),r=Reflect.get(t,"uniformType");if(typeof n!="string"||n.length===0||typeof r!="string"||r.length===0)return;let i=Reflect.get(t,"object"),s=i!==null&&typeof i=="object"?this.#n.get(i):void 0;if(i!==null&&typeof i=="object"&&s===void 0)return;let o=N(Reflect.get(t,"group")),c=o?L().get(o):void 0;if(o&&c===void 0)return;let a=Reflect.get(t,"count");if(a!==null&&(!Number.isSafeInteger(a)||Number(a)<0))return;let d=Reflect.get(t,"name");return {k:"reference",property:n,uniformType:r,...a===null?{}:{count:Number(a)},...s===void 0?{}:{object:s},...c===void 0?{}:{group:c},...typeof d=="string"&&d.length>0?{name:d}:{}}}#f(t){if(R(t)!=="EventNode"||Reflect.get(t,"eventType")!=="object")return;let n=this.#t.builder.object,r=Reflect.get(t,"callback"),i=typeof r=="function"?Function.prototype.toString.call(r):"";if(!p(n)||!i.includes("morphTargetsRelative")||!i.includes("morphTargetInfluences")||!i.includes(".reduce")||!i.includes(".update"))return;let s=n.morphTargetInfluences,o=n.geometry;if(!Array.isArray(s)||!p(o))return;let c=o.morphAttributes;if(!p(c))return;let a=Array.isArray(c.position)?c.position:[],d=Array.isArray(c.normal)?c.normal:[],u=Array.isArray(c.color)?c.color:[],b=a.length>0?a:d.length>0?d:u;if(b.length===0||b.length!==s.length)return;let j=this.#t.journal.some(m=>{let y=Reflect.get(m.node,"value");return R(m.node)==="TextureNode"&&m.type==="texture"&&m.stage==="vertex"&&Reflect.get(m.node,"sampler")===false&&p(y)&&kt(y,o)}),g=this.#t.journal.flatMap((m,y)=>R(m.node)==="UniformArrayNode"?[`${y}:${m.type}/${m.stage}:same=${Reflect.get(m.node,"array")===s}:length=${Array.isArray(Reflect.get(m.node,"array"))?Reflect.get(m.node,"array").length:"na"}`]:[]);if(this.#o.push(`morph=${String(Reflect.get(n,"name")??"")}:targets=${b.length}:influences=${s.length}:texture=${j}:arrays=[${g.join(",")}]`),!j)return;let f=this.#t.journal.flatMap((m,y)=>{let k=Reflect.get(m.node,"array");if(R(m.node)!=="UniformArrayNode"||m.type!=="buffer"||m.stage!=="vertex"||k!==s&&(!Array.isArray(k)||k.length!==s.length))return [];let S=this.#t.journal[y-1];return S===void 0||R(S.node)!=="UniformNode"||S.type!=="float"||S.stage!=="vertex"||typeof Reflect.get(S.node,"value")!="number"||!Number.isFinite(Reflect.get(S.node,"value"))?[]:[{base:S.node,influences:m.node,count:s.length}]});return f.length===1?f[0]:void 0}#p(t){if(R(t)!=="EventNode"||Reflect.get(t,"eventType")!=="object")return;let n=this.#t.builder.object,r=Reflect.get(t,"callback"),i=typeof r=="function"?Function.prototype.toString.call(r):"";if(p(n)&&n.isSkinnedMesh===true&&i.includes("skeleton"))return {k:"recipe",id:P.skinningEvent,version:1};let s=this.#f(t);if(s){let o=this.#e.get(s.base),c=this.#e.get(s.influences);return o===void 0||c===void 0?void 0:{k:"recipe",id:P.morphUpdateEvent,version:1,input:{base:o,influences:c,count:s.count}}}}#g(t){if(R(t)!=="MaxMipLevelNode")return;let n=N(Reflect.get(t,"textureNode"));if(!n)return;let r=this.classify(n,"max-mip texture owner");return {k:"recipe",id:P.maxMip,version:1,input:r}}#m(t){if(R(t)!=="TextureNode"||Reflect.get(t,"sampler")!==false)return;let n=Reflect.get(t,"value"),r=this.#t.builder.object,i=p(r)?r.geometry:void 0;if(!(!p(r)||!p(n)||!p(i)||this.#n.has(n)||Reflect.get(r,"morphTexture")===n||!kt(n,i)))return {k:"recipe",id:P.morphTargetTexture,version:1}}noteUpdateNode(t){if(this.#e.has(t))return;let n=this.#f(t);if(n){let s=Reflect.get(n.influences,"elementType");this.#e.set(n.influences,{k:"inputNode",nodeClass:"uniformArray",value:{container:"@object",path:["morphTargetInfluences"]},access:null,uniformType:typeof s=="string"?s:null});}if(R(t)==="PMREMNode"){let s=this.classify(t,"PMREM update node ownership");for(let o of ["_texture","_width","_height","_maxMip"]){let c=N(Reflect.get(t,o));c&&this.#e.set(c,{k:"owned",owner:s,path:[o]});}return}let r;if(Reflect.get(t,"isMaterialReferenceNode")===true){let s=Reflect.get(t,"property"),o=Reflect.get(t,"uniformType"),c=Reflect.get(t,"referenceType"),a=typeof o=="string"||o===null?o:c;typeof s=="string"&&(typeof a=="string"||a===null)&&(r={k:"materialCache",property:s,type:a});}else r=this.#u(t);if(r===void 0){["TextureNode","Texture3DNode","CubeTextureNode"].includes(R(t))&&(r=this.classify(t,"texture update node ownership"));let s=r===void 0&&Reflect.get(t,"isTextureNode")===true?bt(Reflect.get(t,"value")):void 0;if(p(s)&&s.t==="tex"&&this.classify(t,"update node ownership"),r===void 0)return}this.#e.set(t,r);let i=N(Reflect.get(t,"node"));i&&this.#e.set(i,{k:"owned",owner:r,path:["node"],prime:"reference"});}shouldOmitUpdateNode(t){return R(t)==="InspectorNode"?true:R(t)==="EventNode"&&Reflect.get(t,"eventType")==="frame"&&p(this.#t.builder.object)&&Reflect.get(this.#t.builder.object,"isInstancedMesh")===true}#h(t){let n=this.#t.builder.scene!==null&&typeof this.#t.builder.scene=="object"?this.#t.builder.scene:null,r=this.#s.map((o,c)=>({light:o,address:{light:c}}));for(let[o,c]of ve(n).entries())this.#s.includes(c)||r.push({light:c,address:{light:this.#s.length+o,sceneLight:o}});if(r.length===0)return;if(Reflect.get(t,"isReferenceNode")===true){let o=Reflect.get(t,"object"),c=Reflect.get(t,"property");if(o===null||typeof o!="object"||typeof c!="string")return;let a=Jt[c],d=c==="near"?"shadowCameraNear":c==="far"?"shadowCameraFar":void 0;for(let u of r){let b=Reflect.get(u.light,"shadow");if(!(b===null||typeof b!="object")){if(a!==void 0&&b===o)return {k:"lightUniform",fn:a,...u.address};if(d!==void 0&&Reflect.get(b,"camera")===o)return {k:"lightUniform",fn:d,...u.address}}}return}if(Reflect.get(t,"isUniformNode")!==true)return;let i=Reflect.get(t,"update");if(typeof i!="function"||typeof Reflect.get(t,"value")!="number")return;let s=l(()=>{try{Reflect.apply(i,t,[{}]);}catch{}},"invoke");for(let o of r){let c=Reflect.get(o.light,"shadow"),a=c!==null&&typeof c=="object"?Reflect.get(c,"camera"):void 0;if(!(a===null||typeof a!="object"))for(let d of ["shadowCameraNear","shadowCameraFar"]){let u=d==="shadowCameraNear"?"near":"far",b=Reflect.get(a,u);if(typeof b!="number")continue;let j=b+12345.625,g=false;try{Reflect.set(a,u,j),s(),g=Reflect.get(t,"value")===j;}finally{Reflect.set(a,u,b),s();}if(g)return {k:"lightUniform",fn:d,...o.address}}}}classify(t,n){let r=Reflect.get(t,"name");if(typeof r=="string"&&qt.has(r))return {k:"namedRenderUniform",name:r};let i=this.#e.get(t);if(i)return this.#i(t,n,Nt(i));let s=this.#u(t);if(s)return this.#e.set(t,s),s;let o=this.#p(t);if(o)return this.#e.set(t,o),this.#i(t,n,o);let c=this.#g(t);if(c)return this.#e.set(t,c),this.#i(t,n,c);let a=this.#m(t);if(a){this.#e.set(t,a);let h=Reflect.get(t,"value");return this.#i(t,n,a,h!==null&&typeof h=="object"?h:t)}let d=N(Reflect.get(t,"referenceNode")),u=d!==void 0?this.#e.get(d):void 0;if(n.startsWith("uniform ")&&u!==void 0)return this.#e.set(t,u),u;let b=this.#t.builder.scene!==null&&typeof this.#t.builder.scene=="object"?this.#t.builder.scene:null,j=Reflect.get(t,"light");if(j!==null&&typeof j=="object"){let h=ve(b).indexOf(j);if(h>=0){let w={k:"lightNode",light:h,sceneLight:h};return Reflect.get(t,"isShadowBaseNode")===true?{k:"owned",owner:w,path:["shadowNode"]}:w}}let g=Reflect.get(t,"value"),f=Reflect.get(t,"array");if(g!==null&&typeof g=="object"||f!==null&&typeof f=="object")for(let[h,w]of this.#e){if(h===t)continue;let T=g!==null&&typeof g=="object"&&Reflect.get(h,"value")===g,C=f!==null&&typeof f=="object"&&Reflect.get(h,"array")===f;if(!(!T&&!C)){if(Rt(h,t))return this.#e.set(t,w),w;if(T&&["TextureNode","Texture3DNode","CubeTextureNode"].includes(R(t))){let $=hn(w);if($!==void 0){this.#n.set(g,$);break}}}}if(g!==null&&typeof g=="object")for(let[h,w]of L()){if(Reflect.get(h,"isViewportNode")!==true)continue;let T=N(Reflect.get(h,"_output"));if(T===void 0||Reflect.get(T,"value")!==g||!Rt(T,t))continue;let C={k:"owned",owner:{k:"tsl",name:w},path:["_output"]};return this.#e.set(t,C),C}let m=L().get(t);if(m)return {k:"tsl",name:m};for(let[h,w]of this.#e)for(let T of Object.getOwnPropertyNames(h))if(Reflect.get(h,T)===t){if((w.k==="inputNode"||w.k==="inputValue"||w.k==="recipe")&&!Wt.has(T))continue;let C={k:"owned",owner:w,path:[T]};return this.#e.set(t,C),C}for(let[h,w]of L()){for(let T of Object.getOwnPropertyNames(h))if(Reflect.get(h,T)===t)return {k:"owned",owner:{k:"tsl",name:w},path:[T]};for(let[T,C]of ut(h))if(T===t)return {k:"owned",owner:{k:"tsl",name:w},path:C}}if(R(t)==="ViewportTextureNode"){let h={k:"inputValue",nodeClass:"viewportMipTexture",json:{viewport:this.#l++}};return this.#e.set(t,h),h}if(R(t)==="PassMultipleTextureNode"){let h=N(Reflect.get(t,"passNode")),w=Reflect.get(t,"textureName"),T=Reflect.get(t,"previousTexture")===true?"_previousTextureNodes":"_textureNodes",C=h?this.#e.get(h)??[...this.#e].find(([F])=>N(F)===h)?.[1]:void 0,$=h?Reflect.get(h,T):void 0,V=p($)&&typeof w=="string"?N(Reflect.get($,w)):void 0;if(C&&typeof w=="string"&&V){let F={k:"owned",owner:C,path:[T,w]};return this.#e.set(t,F),F}this.#o.push(`passTexture=${R(h)}/${String(w)}/${T} owner=${C?JSON.stringify(C):"missing"} collection=${R($)} canonical=${R(V)}`);}let y=mn(t);if(y){let h=y==="uniformArray"?Reflect.get(t,"array"):Reflect.get(t,"value"),w=Reflect.get(t,"access"),T=y==="uniformArray"?Reflect.get(t,"elementType"):y==="storage"||y==="buffer"||y==="bufferAttribute"?Reflect.get(t,"bufferType"):Reflect.get(t,"uniformType"),C=typeof w=="string"?w:null,$=typeof T=="string"?T:null,V=N(Reflect.get(t,"group"))??N(Reflect.get(t,"groupNode")),F=V?L().get(V):void 0,qe=F?{group:F}:{},Se=Reflect.get(t,"bufferCount"),We=y==="storage"||y==="buffer"?{bufferCount:Number.isSafeInteger(Se)&&Number(Se)>=0?Number(Se):0,...y==="storage"?{atomic:Reflect.get(t,"isAtomic")===true,pbo:Reflect.get(t,"isPBO")===true}:{}}:{},ee=h!==null&&typeof h=="object"?this.#n.get(h):void 0;if(!ee&&h!==null&&typeof h=="object"){let U=Reflect.get(h,"array");U!==null&&typeof U=="object"&&(ee=this.#n.get(U));}let Je=y==="bufferAttribute"?{stride:Number.isSafeInteger(Reflect.get(t,"bufferStride"))?Number(Reflect.get(t,"bufferStride")):0,offset:Number.isSafeInteger(Reflect.get(t,"bufferOffset"))?Number(Reflect.get(t,"bufferOffset")):0,usage:Number.isSafeInteger(Reflect.get(t,"usage"))?Number(Reflect.get(t,"usage")):0,instanced:Reflect.get(t,"instanced")===true||h!==null&&typeof h=="object"&&(Reflect.get(h,"isInstancedBufferAttribute")===true||Reflect.get(h,"isInstancedInterleavedBuffer")===true)||ee?.path.includes("instanceMatrix")===true||ee?.path.includes("instanceColor")===true}:{},Ye=["texture","cubeTexture","texture3D"].includes(y)&&N(Reflect.get(t,"compareNode"))?{comparison:true}:{},Xe=["texture","cubeTexture"].includes(y)?yn(u):void 0,Ze=Xe??ee,$t=Xe===void 0?y:`${y}Reference`,we=Reflect.get(t,"name"),Qe=typeof we=="string"&&we.length>0?{name:we}:{},H=Ze?{k:"inputNode",nodeClass:$t,value:Ze,access:C,uniformType:$,...Qe,...qe,...We,...Je,...Ye}:void 0;if(!H){let U=bt(h);U!==void 0&&(H={k:"inputValue",nodeClass:y,json:U,access:C,uniformType:$,...Qe,...qe,...We,...Je,...Ye});}if(H){let U=JSON.stringify(H),Ne=this.#d.get(U)??0;this.#d.set(U,Ne+1);let Ut=Ne===0?H:{...H,n:Ne},Ve=Xt(Ut,h);return this.#e.set(t,Ve),this.#i(t,n,Ve,h!==null&&typeof h=="object"?h:t)}}let k=this.#h(t);if(k)return this.#e.set(t,k),this.#i(t,n,k);let S=l(h=>R(h)===R(t)&&R(Reflect.get(h,"value"))===R(Reflect.get(t,"value"))&&Reflect.get(h,"updateType")===Reflect.get(t,"updateType"),"comparable"),v=[...L()].filter(([h])=>S(h)).slice(0,8).map(([,h])=>h),ke=[...this.#e].filter(([h])=>S(h)).slice(0,8).map(([h,w])=>`${JSON.stringify(w)}@${ft(Reflect.get(h,"value"))}`),M=p(Reflect.get(t,"value"))?Reflect.get(Reflect.get(t,"value"),"uuid"):void 0,Z=typeof M=="string"?[...this.#e].filter(([h])=>p(Reflect.get(h,"value"))&&Reflect.get(Reflect.get(h,"value"),"uuid")===M).slice(0,12).map(([h,w])=>`${R(h)}:${JSON.stringify(w)}`):[],Q=I("containers",[this.#t.scene]),_t=Array.isArray(Q)?Q.slice(0,64).flatMap(h=>{if(!p(h)||typeof h.key!="string"||!p(h.target))return [];let w=h.target,T=Object.keys(w).filter(C=>Reflect.get(w,C)===Reflect.get(t,"value"));return [`${h.key}/${R(w)}${T.length>0?`:${T.join(",")}`:""}`]}):[],Ge=R(t)==="EventNode"?Reflect.get(t,"callback"):void 0,Mt=typeof Ge=="function"?Function.prototype.toString.call(Ge).replaceAll(/\s+/gu," ").slice(0,320):void 0,E=this.#t.builder.object;throw new Error(`Cannot address ${R(t)}${typeof r=="string"&&r?` "${r}"`:""} used by ${n} for shader key "${this.#t.key}". Node metadata: value=${R(Reflect.get(t,"value"))}, update=${typeof Reflect.get(t,"update")=="function"?Reflect.get(t,"update").name||"anonymous":"none"}, updateType=${String(Reflect.get(t,"updateType"))}.`+(y?` Input metadata: class=${y}, value=${R(Reflect.get(t,"value"))}, access=${String(Reflect.get(t,"access"))}, uniformType=${String(Reflect.get(t,"uniformType"))}.`:"")+` Similar semantic inputs: tsl=[${v.join(", ")}], paths=[${ke.join(", ")}].`+(p(Reflect.get(t,"value"))&&Reflect.get(Reflect.get(t,"value"),"isTexture")===true?` Texture value: ${ft(Reflect.get(t,"value"))}.`:"")+(Z.length>0?` Same-texture paths: [${Z.join(", ")}].`:"")+` Classifier diagnostics: ${this.#o.join("; ")}. Registered containers: [${_t.join(", ")}].`+(Reflect.get(t,"isStorageBufferNode")===true?` Storage metadata: type=${String(Reflect.get(t,"bufferType"))}, count=${String(Reflect.get(t,"bufferCount"))}, value=${R(Reflect.get(t,"value"))}.`:"")+(R(t)==="MaterialReferenceNode"?` Material reference metadata: flag=${String(Reflect.get(t,"isMaterialReferenceNode"))}, property=${String(Reflect.get(t,"property"))}, uniformType=${String(Reflect.get(t,"uniformType"))}.`:"")+(R(t)==="EventNode"?` Event metadata: type=${String(Reflect.get(t,"eventType"))}, object=${R(E)}, objectName=${p(E)?String(E.name??""):""}, instanced=${p(E)&&E.isInstancedMesh===true}, skinned=${p(E)&&E.isSkinnedMesh===true}, morphs=${p(E)&&Array.isArray(E.morphTargetInfluences)?E.morphTargetInfluences.length:0}, callback=${Mt??"none"}.`:""))}};function Be(e){return Array.isArray(e)?e.map(N).filter(t=>t!==void 0):[]}l(Be,"nodeArray");function bn(e,t,n){let r=t.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&"),i=new RegExp(`struct\\s+${r}Struct\\s*\\{([\\s\\S]*?)\\};`,"u"),s=[e.vertexShader,e.fragmentShader,e.computeShader].filter(a=>typeof a=="string"),o;for(let a of s){let d=i.exec(a)?.[1];if(d!==void 0&&(o=[...d.matchAll(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*:/gmu)].map(u=>u[1]).filter(u=>u!==void 0),o.length>0))break}if(!o||o.length===0)return;let c=new Map(n.map(a=>[a.name,a.type]));if(!o.some(a=>!c.has(a)))return o.map(a=>({name:a,type:c.get(a)}))}l(bn,"wgslUniformLayout");var Rn=[{directive:/(?:^|\n)\s*enable\s+subgroups\s*;/u,feature:"subgroups"},{directive:/(?:^|\n)\s*enable\s+subgroups[-_]f16\s*;/u,feature:"subgroups-f16"},{directive:/(?:^|\n)\s*enable\s+f16\s*;/u,feature:"shader-f16"},{directive:/(?:^|\n)\s*enable\s+clip_distances\s*;/u,feature:"clip-distances"},{directive:/(?:^|\n)\s*enable\s+dual_source_blending\s*;/u,feature:"dual-source-blending"}];function kn(e){let t=[];for(let n of Rn)e.some(r=>r!==null&&n.directive.test(r))&&t.push(n.feature);return t}l(kn,"shaderRequirements");function Sn(e,t){let n=new Map,r=new Set,i=[];for(let s of e){let o=t(s.node,`uniform ${s.name??"<generated>"}`),c=JSON.stringify(o),a=n.get(c);a===void 0&&(a=new Map,n.set(c,a));let d=a.get(s.nid);d===void 0&&(d=a.size,a.set(s.nid,d));let u=`${c}\0${d}\0${s.stage}`;r.has(u)||(r.add(u),i.push({address:o,instance:d,type:s.type,stage:s.stage,name:s.name}));}return i}l(Sn,"reduceJournal");function wn(e,t){if(t==="NodeStorageBuffer"||t==="StorageBuffer"){let n=e.access;return typeof n=="string"?{access:n}:{}}if(t.includes("Sampled")){let n=e.store===true,r=e.access;return {store:n,...n&&typeof r=="string"?{access:r}:{}}}return {}}l(wn,"capturedBindingAccess");function Nn(e,t){let n=ze(e.builder,e.kind);if(!n)throw new Error(`Shader key "${e.key}" has no live build target.`);let r=new Ke({...e,target:n},t),i=Be(e.builder.updateNodes),s=Be(e.builder.updateBeforeNodes),o=Be(e.builder.updateAfterNodes);for(let f of [...i,...s,...o])r.noteUpdateNode(f);let c=Sn(e.journal,(f,m)=>r.classify(f,m)),a=typeof e.builder.getAttributesArray=="function"?Reflect.apply(e.builder.getAttributesArray,e.builder,[]):[],d=Array.isArray(a)?a.map((f,m)=>{if(!p(f)||typeof f.name!="string"||typeof f.type!="string")throw new Error(`Shader attribute ${m} is invalid.`);let y=N(f.node);return {name:f.name,type:f.type,node:y?r.classify(y,`attribute ${f.name}`):null}}):[],u=typeof e.builder.getBindings=="function"?Reflect.apply(e.builder.getBindings,e.builder,[]):[],b=Array.isArray(u)?u.map((f,m)=>{if(!p(f)||!Array.isArray(f.bindings))throw new Error(`Shader bind group ${m} is invalid.`);return {name:typeof f.name=="string"?f.name:`group-${m}`,bindings:f.bindings.map((y,k)=>{if(!p(y)||typeof y.name!="string")throw new Error(`Shader binding ${m}/${k} is invalid.`);let S=je(y),v;if(S==="NodeUniformsGroup"){if(!Array.isArray(y.uniforms))throw new Error(`Shader uniform group ${m}/${k} has no member list.`);let ke=y.uniforms.map((M,Z)=>{if(!p(M)||typeof M.name!="string"||typeof M.getType!="function")throw new Error(`Shader uniform ${m}/${k}/${Z} is invalid.`);let Q=Reflect.apply(M.getType,M,[]);if(typeof Q!="string")throw new Error(`Shader uniform ${m}/${k}/${Z} has no stable type.`);return {name:M.name,type:Q}});v=bn(e.builder,y.name,c)??ke;}return {name:y.name,kind:S,...wn(y,S),...v===void 0?{}:{uniforms:v}}})}}):[],j=p(e.builder.observer)?{hasNode:e.builder.observer.hasNode===true,hasAnimation:e.builder.observer.hasAnimation===true}:null,g=l(f=>typeof e.builder[f]=="string"?e.builder[f]:null,"shader");return {key:e.key,vertexShader:g("vertexShader"),fragmentShader:g("fragmentShader"),computeShader:g("computeShader"),declarations:c,attributes:d,bindGroups:b,updateNodes:i.filter(f=>!r.shouldOmitUpdateNode(f)).map(f=>r.classify(f,"updateNodes")),updateBeforeNodes:s.filter(f=>!r.shouldOmitUpdateNode(f)).map(f=>r.classify(f,"updateBeforeNodes")),updateAfterNodes:o.filter(f=>!r.shouldOmitUpdateNode(f)).map(f=>r.classify(f,"updateAfterNodes")),requirements:kn([g("vertexShader"),g("fragmentShader"),g("computeShader")]),observer:j,hardwareClipping:e.builder.hardwareClipping===true}}l(Nn,"entryFromSnapshot");function q(e){return (e??"").replace(/\b(nodeUniform|nodeVar|nodeVarying|nodeAttribute|NodeBuffer_|nodeCode)\d+\b/gu,"$1#").split(`
|
|
2
|
+
`).sort().join(`
|
|
3
|
+
`)}l(q,"canonicalShader");var O=class{static{l(this,"CapturePool");}values=[];#t=new Map;intern(t,n=JSON.stringify(t)){let r=this.#t.get(n);return r===void 0&&(r=this.values.length,this.#t.set(n,r),this.values.push(t)),r}};function An(e){let t=new O,n=new O,r=new O,i=new O,s=new O,o=new O,c=new O,a={};for(let d of Object.keys(e).sort()){let u=e[d];if(u===void 0)continue;let b=l(m=>m===null?null:t.intern(m,m),"moduleAt"),j=u.declarations.map(m=>[n.intern(m.address),m.instance,m.type,m.stage,m.name]),g=u.requirements.length===0?void 0:o.intern(u.requirements),f={vertex:b(u.vertexShader),fragment:b(u.fragmentShader),compute:b(u.computeShader),declarations:j,layout:r.intern(u.bindGroups),attributes:i.intern(u.attributes.map(m=>({name:m.name,type:m.type,node:m.node===null?null:n.intern(m.node)}))),updates:[s.intern(u.updateNodes.map(m=>n.intern(m))),s.intern(u.updateBeforeNodes.map(m=>n.intern(m))),s.intern(u.updateAfterNodes.map(m=>n.intern(m)))],...g===void 0?{}:{requirements:g},observer:u.observer,hardwareClipping:u.hardwareClipping};a[d]=c.intern(f);}return {modules:t.values,nodes:n.values,layouts:r.values,attributePlans:i.values,updatePlans:s.values,requirementPlans:o.values,states:c.values,entries:a}}l(An,"poolCaptureEntries");function Tn(e,t){let n={},r=[],i=new De;for(let s of pe.filter(o=>o.scene===e))try{let o=Nn(s,i),c=Le(o);if(c)throw new Error(`Shader key "${o.key}" captured the automatic input container "${c}". Automatically discovered input containers are capture-only; register a stable application container or retain the value under the material/compute root.`);let a=Ie(o);if(a)throw new Error(`Shader key "${o.key}" captured the transient renderer path "${a}". Renderer contexts must use a semantic recipe, and renderer back-references are never stable replay roots.`);let d=n[o.key];d?(q(d.vertexShader)!==q(o.vertexShader)||q(d.fragmentShader)!==q(o.fragmentShader)||q(d.computeShader)!==q(o.computeShader))&&r.push(`Shader key "${o.key}" produced conflicting structures in one capture.`):n[o.key]=o;}catch(o){r.push(o instanceof Error?o.stack??o.message:String(o));}return {protocolVersion:2,compatibility:Ae,scene:e,..._===void 0?{}:{automatic:{prefix:_}},...An(n),skipped:[...ge],errors:r,stats:{...x},timing:{...J===void 0?{}:{readiness:J},...Y===void 0?{}:{lastBuild:Y},settled:Date.now()},provenance:t}}l(Tn,"buildPayload");async function jn(){let e=globalThis,t=p(e.navigator)?e.navigator:{},n=pe.find(u=>u.scene===K)?.renderer,r=p(n?.backend)?n.backend:{},i=p(r.device)?r.device:{},s=p(i.adapterInfo)?i.adapterInfo:void 0;if(s===void 0&&p(t.gpu)&&typeof t.gpu.requestAdapter=="function"){let u=await Promise.race([Promise.resolve(Reflect.apply(t.gpu.requestAdapter,t.gpu,[])).catch(()=>{}),new Promise(b=>setTimeout(()=>b(void 0),zt))]);p(u)&&(s=p(u.info)?u.info:u);}let o=["description","device","architecture","vendor"].flatMap(u=>{let b=s?.[u];return typeof b=="string"&&b.length>0?[b]:[]}),c=i.features,d=typeof(c!==null&&typeof c=="object"?Reflect.get(c,Symbol.iterator):void 0)=="function"?[...c].filter(u=>typeof u=="string").sort():[];return {userAgent:typeof t.userAgent=="string"?t.userAgent:"unknown browser",adapter:[...new Set(o)].join(" \xB7 ")||"WebGPU adapter",features:d}}l(jn,"captureProvenance");function Ee(e){if(A.captureId===void 0)return;let t=Reflect.get(globalThis,"dispatchEvent"),n=Reflect.get(globalThis,"CustomEvent");if(!(typeof t!="function"||typeof n!="function"))try{let r=Reflect.construct(n,["three-blocks:shader-capture",{detail:{...e,active:!0}}]);Reflect.apply(t,globalThis,[r]);}catch{}}l(Ee,"publishOverlayCaptureState");async function ie(e,t){let n=A.captureId!==void 0,r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",...A.token===void 0?{}:{"X-Three-Blocks-Capture-Token":A.token}},body:JSON.stringify(n?{captureId:A.captureId,payload:t}:t)});if(!r.ok){let i=await r.text().catch(()=>""),s=i;try{let o=JSON.parse(i);p(o)&&typeof o.error=="string"&&(s=o.error);}catch{}throw n&&Ee({stage:"error",scene:K,error:s||`Shader devtools endpoint ${e} returned HTTP ${r.status}.`}),new Error(s||`Shader devtools endpoint ${e} returned HTTP ${r.status}.`)}if(n&&e===oe&&p(t)&&Ee(t),n&&e===$e){let i=await r.json().catch(()=>{}),s=p(i)&&Number.isSafeInteger(i.pipelines)?Number(i.pipelines):0;Ee({stage:"complete",scene:K,pipelines:s});}if(e===$e&&A.sessionKey!==void 0)try{let i=Reflect.get(globalThis,"sessionStorage"),s=p(i)?i.removeItem:void 0;typeof s=="function"&&Reflect.apply(s,i,[A.sessionKey]);}catch{}}l(ie,"postJson");async function _e(){await ie(oe,le(true,"writing")),A.capture&&!se&&(await ie($e,Tn(K,await jn())),se=true,ce++,D&&clearTimeout(D),D=void 0);}l(_e,"reportSettled");function Me(e){console.error("[three-blocks] shader capture report failed",e);}l(Me,"reportSettledFailure");function le(e,t=e?"writing":"building"){return {protocolVersion:1,compatibility:Ae,transform:A.transform,scene:K,settled:e,stage:t,stats:{...x},timing:{...J===void 0?{}:{readiness:J},...Y===void 0?{}:{lastBuild:Y},...e?{settled:Date.now()}:{}},..._===void 0?{}:{automatic:{prefix:_}},skipped:[...ge]}}l(le,"telemetryPayload");function Cn(e,t){let n=e;for(let r of t.split(".")){if(!p(n)&&typeof n!="function")return;n=Reflect.get(n,r);}return n}l(Cn,"readinessGlobalValue");function xn(e,t=A.readiness){if(t.selector!==void 0){let n=Reflect.get(e,"document");if(!p(n))return false;let r=Reflect.get(n,"querySelector");if(typeof r!="function"||Reflect.apply(r,n,[t.selector])===null)return false}if(t.global!==void 0){let n=Cn(e,t.global);return n===true?true:Tt(n)?(n!==ne&&(ne=n,re=false,Promise.resolve(n).then(()=>{ne===n&&(re=true);},r=>{ne===n&&(re=false),console.error(`[three-blocks] shader readiness global ${t.global} rejected`,r);})),re):false}return true}l(xn,"pageLoadingIsComplete");function Et(){if(A.capture&&se)return;Ce||(Ce=true,queueMicrotask(()=>{Ce=false,ie(oe,le(false)).catch(()=>{});})),D&&clearTimeout(D);let e=++ce,t=globalThis,n=t.requestAnimationFrame;if(typeof n=="function"&&A.settleFrames>0){let i=A.settleFrames,s=l(()=>{if(e!==ce)return;if(!xn(t)){Reflect.apply(n,t,[s]);return}let o=Date.now();J??=o,de??=o;let c=Reflect.get(t,"document"),a=Reflect.get(globalThis,Symbol.for("three-blocks.shader-capture.worker-visible.v1")),d=A.visibilityGuard&&(p(c)&&c.hidden===true||a===false),u=Math.max(0,o-de);if(de=o,d){W||(W=true,ie(oe,le(false,"hidden")).catch(()=>{})),Reflect.apply(n,t,[s]);return}if(Oe+=Math.min(u,250),W||(W=true,ie(oe,le(false,"settling")).catch(()=>{})),Oe>=(A.settleTimeoutMs??3e4)){_e().catch(Me);return}if(i--,i<=0){_e().catch(Me);return}Reflect.apply(n,t,[s]);},"frame");Reflect.apply(n,t,[s]);return}let r=Math.max(250,Math.min(3e4,A.settleFrames*(1e3/60)));D=setTimeout(()=>{D=void 0,e===ce&&_e().catch(Me);},r);}l(Et,"scheduleSettledReport");export{Ct as activeShaderCaptureScene,je as capturedBindingKind,Qt as configureThreeBlocksShaderCapture,vt as instrumentThreeBlocksShaderBuilder,xn as pageLoadingIsComplete,sn as prepareThreeBlocksShaderRenderer,Bt as recordThreeBlocksShaderBuild,pt as wrapThreeBlocksCaptureTimedBuild};
|