@three-blocks/devtools 9.0.0 → 10.0.0-alpha.383.g7a1b8e66c904

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 CHANGED
@@ -1,5 +1,68 @@
1
1
  # @three-blocks/devtools
2
2
 
3
+ ## 10.0.0-alpha.383.g7a1b8e66c904
4
+
5
+ - Website: Example previews and precompiled shaders now match the current release.
6
+
7
+ - Library: Large PLY splat files now load through bundled workers.
8
+
9
+ - Devtools: Shader checks bound browser startup and shutdown before the next verification.
10
+
11
+ - Library: Baked Motion automatically prefers HEVC and falls back to AVC on every device.
12
+
13
+ - Library: Baked Motion can author narrower depth tracks to reduce package downloads.
14
+
15
+ - Library: Baked Motion bounds tilt warp reprojection so a starved blend goes stale, not stretched.
16
+
17
+ - Packages: Gaussian benchmarks add the three.js GaussianSplat runtime on its matching dev build.
18
+
19
+ - Library: Gaussian splats keep equal-depth ordering stable and avoid duplicate tile staging.
20
+
21
+ - Library: HMR replaces outgoing shader registrations without reporting false conflicts.
22
+
23
+ - Starter: New projects install the current Three Blocks and Devtools releases.
24
+
25
+ - Tools: Exact-count splats no longer drop small mesh objects with dense triangulation.
26
+
27
+ - Library: WaterVolume keeps hydrostatic density stable at high particle counts.
28
+
29
+ - Library: Sphere rasterization ignores inconsistent overflow readbacks instead of rebuilding.
30
+
31
+ - Website: The water surface demo starts at 500K particles, caps at 1M, and opens wider.
32
+
33
+ - Website: Water demos add larger tiers and a tunable floorless monochrome PBR particle view.
34
+
35
+ - Website: Example recording mode hides every interface except the rendered canvas.
36
+
37
+ - Website: The body-tracking demo now shows the whole live SDF volume instead of one slice.
38
+
39
+ - Library: SDFFieldNodes provides reusable distance, normal, shadow, and occlusion nodes.
40
+
41
+ - Website: Login, setup, and tool stories now use polished, selectable terminals.
42
+
43
+ - Library: Baked Motion preserves atlas alpha, resolves paused seeks, and fits mobile budgets.
44
+
45
+ - Library: Baked Motion tilt packages can ship a coarse all-view atlas for undecoded corners.
46
+
47
+ - Library: Baked Motion and Gaussian splat types now match their supported runtime contracts.
48
+
49
+ - Library: Baked Motion fuses each atlas page into one RGBA texture, halving its GPU memory.
50
+
51
+ - Tools: Baked Motion writes one package format; timelines and camera grids no longer differ.
52
+
53
+ - Tools: Baked Motion can now publish verified HEVC renditions alongside H.264.
54
+
55
+ - Tools: Blender reports consistent hub and Mesh to Splat versions in every install mode.
56
+
57
+ - Website: The launch film now opens on its title and keeps every proof to one fast minute.
58
+
59
+ - Library: Water accepts a shared interaction world, so moving bodies can push it.
60
+
61
+ - Packages: Indirect batching and its dependent examples are no longer included.
62
+
63
+ - Packages: Built from `7a1b8e66c904`.
64
+
65
+
3
66
  ## 9.0.0
4
67
 
5
68
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {d}from'./chunk-EE64MV27.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import'./chunk-65VEJRRT.js';import {b,a as a$1,c,h,d as d$1,f}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {readFile,lstat,readdir,realpath,mkdir}from'fs/promises';import i from'path';import {read,KHR_DF_PRIMARIES_BT709,write}from'ktx-parse';var U=2,ie="ktx2-encoder@0.6.0",ae=i.join(".three-blocks","assets"),ue=i.join(ae,"meta.json"),we=i.join(ae,"cache"),Te=256*1024*1024,Ae=64*1024*1024,ee=115e5,te=64,Ee=163,Re=166,ve=167,Se=1000066e3,de=1,le=2,$e=/baseColor|emissive|diffuse|sheenColor|specularColor/u,Me=/normal/iu,Oe=/(?:^|[_\-.])(?:normal|nrm|nor)(?:[_\-.]|map|$)/iu,_e=/(?:rough|metal|orm\b|occlusion|ambient|[_\-.]ao(?:[_\-.]|$)|height|disp|thick|mask)/iu;function Ie(t){return t.some(e=>Me.test(e))?"normal":t.some(e=>$e.test(e))||t.length===0?"color":"data"}a(Ie,"presetForTextureSlots");function De(t){let e=i.basename(t);return Oe.test(e)?"normal":_e.test(e)?"data":"color"}a(De,"presetForImageName");function V(t){let e=i.extname(t).toLowerCase();return e===".glb"?"glb":e===".png"||e===".jpg"||e===".jpeg"||e===".webp"?"image":e===".hdr"?"hdr":null}a(V,"assetKindFor");function P(t,e){let r=i.relative(t,e);return (r!==""&&!r.startsWith("..")&&!i.isAbsolute(r)?r:e).split(i.sep).join("/")}a(P,"portable");var X;function ce(){return X??=Promise.all([import('ktx2-encoder'),import('sharp')]).then(([t,e])=>({encodeToKTX2:t.encodeToKTX2,sharp:e.default})),X}a(ce,"loadEncoderTools");function me(t,e){let r=e.quality==="high";return t==="hdr"?{mode:"uastc-hdr",options:{isHDR:true,imageType:"hdr",isUASTC:true,isYFlip:true,generateMipmap:true,needSupercompression:true,hdrQualityLevel:r?2:1}}:t==="color"&&!r?{mode:"etc1s",options:{isUASTC:false,qualityLevel:160,compressionLevel:2,isPerceptual:true,isSRGB:true,generateMipmap:true}}:{mode:"uastc",options:{isUASTC:true,uastcLDRQualityLevel:r?2:1,enableRDO:true,rdoQualityLevel:1,generateMipmap:true,needSupercompression:true,isPerceptual:t==="color",isSRGB:t==="color",isNormalMap:t==="normal"}}}a(me,"encoderOptionsFor");function Le(t,e){let r=read(t),s=r.dataFormatDescriptor[0];if(s===void 0)return t;let n=e==="color"?le:de;return s.transferFunction===n&&(e!=="color"||s.colorPrimaries===KHR_DF_PRIMARIES_BT709)?t:(s.transferFunction=n,e==="color"&&(s.colorPrimaries=KHR_DF_PRIMARIES_BT709),write(r,{keepWriter:true}))}a(Le,"normalizeDfdTransfer");function he(t,e,r,s){let n=read(t),o=n.dataFormatDescriptor[0];if(o===void 0)throw new Error(`${s} produced a KTX2 container without a data format descriptor.`);if(e==="hdr"){if(n.vkFormat!==Se||o.colorModel!==ve)throw new Error(`${s} is not a UASTC HDR container (vkFormat ${n.vkFormat}, color model ${o.colorModel}).`)}else {let c=r==="etc1s"?Ee:Re;if(n.vkFormat!==0||o.colorModel!==c)throw new Error(`${s} is not a ${r} container (vkFormat ${n.vkFormat}, color model ${o.colorModel}).`)}let a=e==="color",u=o.transferFunction;if(a&&u!==le)throw new Error(`${s} must carry the sRGB transfer function; found ${u}.`);if(!a&&u!==de)throw new Error(`${s} must carry the linear transfer function; found ${u}.`);if(Math.max(n.pixelWidth,n.pixelHeight)>=8&&n.levels.length<2)throw new Error(`${s} is missing its mip chain.`);return {width:n.pixelWidth,height:n.pixelHeight,levels:n.levels.length}}a(he,"verifyKtx2");async function ye(t,e,r,s){let{encodeToKTX2:n,sharp:o}=await ce(),a$1=r.maxDimension,{mode:u,options:c}=me(e,r),d=performance.now(),m=false,p=Le(await n(t,{...c,imageDecoder:a(async $=>{let E=o($),M=await E.metadata(),O=M.width??0,b=M.height??0;if(O<1||b<1)throw new Error(`${s} has no decodable dimensions.`);let y=Math.min(1,a$1/Math.max(O,b));O*y*b*y>ee&&(y=Math.sqrt(ee/(O*b)));let x=y<1,w=x?Math.max(4,Math.floor(O*y/4)*4):O,I=x?Math.max(4,Math.floor(b*y/4)*4):b,_=x?E.resize(w,I,{fit:"fill",kernel:"lanczos3"}):E,{data:h,info:v}=await _.ensureAlpha().raw().toBuffer({resolveWithObject:true});for(let S=3;S<h.byteLength;S+=4)if(h[S]!==255){m=true;break}return {data:new Uint8Array(h.buffer,h.byteOffset,h.byteLength),width:v.width,height:v.height}},"decode")}),e),{width:f,height:R,levels:g}=he(p,e,u,s);return {bytes:p,width:f,height:R,levels:g,hasAlpha:m,mode:u,durationMs:performance.now()-d}}a(ye,"encodeLdrTexture");function Be(t,e){let r=new TextDecoder("latin1").decode(t.subarray(0,Math.min(t.byteLength,4096))),s=/-Y\s+(\d+)\s+\+X\s+(\d+)/u.exec(r);if(s?.[1]===void 0||s[2]===void 0)throw new Error(`${e} is not a supported Radiance .hdr file (missing "-Y <h> +X <w>" resolution).`);return {width:Number(s[2]),height:Number(s[1])}}a(Be,"hdrDimensions");async function ke(t,e,r){let s=Be(t,r);if(Math.max(s.width,s.height)>e.hdrMaxDimension)throw new Error(`${r} is ${s.width}x${s.height}, above the ${e.hdrMaxDimension}px HDR cap; resize the source (HDR resize is not supported yet).`);let{encodeToKTX2:n}=await ce(),{mode:o,options:a}=me("hdr",e),u=performance.now(),c=await n(t,a),{width:d,height:m,levels:A}=he(c,"hdr",o,r);return {bytes:c,width:d,height:m,levels:A,hasAlpha:false,mode:o,durationMs:performance.now()-u}}a(ke,"encodeHdrTexture");function pe(t,e,r,s){let n=0,o=t,a=e;for(let u=0;u<r;u+=1)n+=o*a*s,o=Math.max(1,o>>1),a=Math.max(1,a>>1);return n}a(pe,"uncompressedMipBytes");function q(t,e,r,s){let n=0,o=t,a=e;for(let u=0;u<r;u+=1)n+=Math.ceil(o/4)*Math.ceil(a/4)*s,o=Math.max(1,o>>1),a=Math.max(1,a>>1);return n}a(q,"compressedMipBytes");function fe(t,e){return t==="etc1s"&&!e?8:16}a(fe,"transcodedBlockBytes");async function Fe(t,e,r){let s=r.preset??De(e),n=`Image ${JSON.stringify(i.basename(e))}`,o=await ye(t,s,r,n),a=[`preset ${s} (${r.preset===null?"from filename":"explicit"})`];return s!=="color"&&a.push("linear DFD: consumers must treat this texture as non-color data"),a.push("compressed textures never flip: sample with glTF-style (flipY=false) UVs"),{bytes:o.bytes,metadata:{vramBytesIn:pe(o.width,o.height,o.levels,4),vramBytesOut:q(o.width,o.height,o.levels,fe(o.mode,o.hasAlpha)),textures:[{name:i.basename(e),slots:[],preset:s,mode:o.mode,width:o.width,height:o.height,bytesIn:t.byteLength,bytesOut:o.bytes.byteLength,durationMs:Math.round(o.durationMs)}],notes:a}}}a(Fe,"buildImageAsset");async function Pe(t,e,r){let s=`Environment ${JSON.stringify(i.basename(e))}`,n=await ke(t,r,s);return {bytes:n.bytes,metadata:{vramBytesIn:n.width*n.height*8,vramBytesOut:q(n.width,n.height,n.levels,16),textures:[{name:i.basename(e),slots:["equirectangular"],preset:"hdr",mode:n.mode,width:n.width,height:n.height,bytesIn:t.byteLength,bytesOut:n.bytes.byteLength,durationMs:Math.round(n.durationMs)}],notes:["BC6H on BC-capable devices; transcodes to RGBA16F elsewhere"]}}}a(Pe,"buildHdrAsset");async function Ne(t,e,r,s){let[{Logger:n,NodeIO:o},{ALL_EXTENSIONS:a,KHRTextureBasisu:u},{dedup:c,listTextureSlots:d,meshopt:m,prune:A,weld:p},{MeshoptDecoder:f,MeshoptEncoder:R}]=await Promise.all([import('@gltf-transform/core'),import('@gltf-transform/extensions'),import('@gltf-transform/functions'),import('meshoptimizer')]);await R.ready,await f.ready;let g=new o().registerExtensions(a).registerDependencies({"meshopt.encoder":R,"meshopt.decoder":f}),$=`GLB ${JSON.stringify(i.basename(e))}`;g.setLogger(new n(n.Verbosity.SILENT));let E=await g.readBinary(t);E.setLogger(new n(n.Verbosity.SILENT));let M=E.getRoot().listTextures();if(M.length>0&&M.every(h=>h.getMimeType()==="image/ktx2")&&E.getRoot().listExtensionsUsed().some(h=>h.extensionName==="EXT_meshopt_compression"))return {bytes:t,metadata:{vramBytesIn:0,vramBytesOut:0,textures:[],notes:["already optimized (KTX2 + meshopt); copied unchanged"]}};s?.("optimizing geometry"),await E.transform(c(),A({keepAttributes:true,keepExtras:true,keepSolidTextures:true}),p(),m({encoder:R,level:"medium"}));let b=[],y=[],x=0,w=0,I=0;for(let h of M){let v=h.getName()||h.getURI()||`texture-${b.length}`,S=h.getImage(),k=h.getMimeType();if(S===null||S.byteLength===0)continue;if(k==="image/ktx2"){y.push(`${v}: already KTX2, kept`);continue}if(!/^image\/(?:png|jpeg|webp)$/u.test(k)){y.push(`${v}: unsupported ${k}, kept`);continue}let z=h.getSize();if(z!==null&&Math.max(z[0],z[1])<te){y.push(`${v}: below ${te}px, kept`);continue}let W=d(h),j=Ie(W);s?.(`encoding ${v} (${j})`);let T=await ye(new Uint8Array(S),j,r,`${$} texture ${JSON.stringify(v)}`);h.setImage(T.bytes).setMimeType("image/ktx2");let G=h.getURI();G!==""&&h.setURI(G.replace(/\.(?:png|jpe?g|webp)$/iu,".ktx2")),I+=1,x+=pe(T.width,T.height,T.levels,4),w+=q(T.width,T.height,T.levels,fe(T.mode,T.hasAlpha)),b.push({name:v,slots:W,preset:j,mode:T.mode,width:T.width,height:T.height,bytesIn:S.byteLength,bytesOut:T.bytes.byteLength,durationMs:Math.round(T.durationMs)});}I>0&&E.createExtension(u).setRequired(true);let _=await g.writeBinary(E);return await g.readBinary(_),I>0&&y.push("requires a KTX2-wired loader (three-blocks/assets or GLTFLoader.setKTX2Loader)"),{bytes:_,metadata:{vramBytesIn:x,vramBytesOut:w,textures:b,notes:y}}}a(Ne,"buildGlbAsset");function Ce(t,e,r){let s=i.basename(t,i.extname(t));if(e==="glb"){let n=r===null?i.join(i.dirname(t),`${s}.tb.glb`):i.join(r,`${s}.glb`);if(i.resolve(n)===i.resolve(t))throw new Error(`Output would overwrite the input: ${JSON.stringify(t)}. Pass a different output directory.`);return n}return i.join(r??i.dirname(t),`${s}.ktx2`)}a(Ce,"outputPathFor");async function ge(t){let e={schemaVersion:U,tool:{name:"three-blocks-devtools",assetOptimizeVersion:U,encoder:ie},assets:{}},r;try{r=await readFile(t,"utf8");}catch(s){if(b(s)==="ENOENT")return e;throw s}if(r.length>a$1.receipt)return e;try{let s=JSON.parse(r);if(typeof s!="object"||s===null)return e;let n=s;return n.schemaVersion!==U||typeof n.assets!="object"||n.assets===null?e:{...e,assets:{...n.assets}}}catch{return e}}a(ge,"readReceipt");async function Ue(t){let e=[];for(let r of t){let s=i.resolve(r);if((await lstat(s)).isDirectory()){let o=[s],a=0;for(;o.length>0;){let u=o.shift();if(u===void 0)break;let c=(await readdir(u,{withFileTypes:true})).sort((d,m)=>d.name.localeCompare(m.name));for(let d of c){if(a+=1,a>8192)throw new Error("Input directory expansion exceeds the 8192-entry limit.");if(d.isSymbolicLink()||d.name.startsWith("."))continue;let m=i.join(u,d.name);if(d.isDirectory()){d.name!=="three-blocks"&&o.push(m);continue}d.isFile()&&!d.name.endsWith(".tb.glb")&&V(d.name)!==null&&e.push(m);}}}else e.push(s);}if(e.length===0)throw new Error("No optimizable inputs found (.glb, .png, .jpg, .webp, .hdr).");return e}a(Ue,"expandInputs");async function Ve(t){let e=await realpath(t.root),r={maxDimension:re(t.maxDimension,2048),hdrMaxDimension:re(t.hdrMaxDimension,4096),quality:t.quality??"default",preset:t.preset??null},s=t.outDir===void 0?null:i.resolve(e,t.outDir);s!==null&&await mkdir(s,{recursive:true});let n=i.join(e,we),o=i.join(e,ue),a$2=c(d({version:U,encoder:ie,...r})),u=await Ue(t.inputs),c$1=[],d$2=[],m=await ge(o);for(let[A,p]of u.entries()){let f$1=V(p);try{if(f$1===null)throw new Error(`Unsupported asset type ${JSON.stringify(i.extname(p))}; expected .glb, .png, .jpg, .webp, or .hdr (EXR sources are not supported yet \u2014 convert environments to .hdr).`);t.onProgress?.(`${i.basename(p)} (${A+1}/${u.length})`);let R=f$1==="glb"?Te:f$1==="hdr"?Ae:a$1.texture,g=await h(p,R,"Asset input"),$=g.path,E=c(g.data),M=c(`${E}\0${a$2}`),O=f$1==="glb"?"glb":"ktx2",b=i.join(n,`${M}.${O}`),y=i.join(n,`${M}.json`),x,w,I=!1;if(t.force!==!0&&await d$1(b)&&await d$1(y))x=(await h(b,R,"Cached asset")).data,w=JSON.parse((await h(y,a$1.metadata,"Cached asset metadata")).data.toString("utf8")),I=!0;else {let v=a(k=>t.onProgress?.(`${i.basename(p)}: ${k}`),"progress"),S=f$1==="glb"?await Ne(g.data,$,r,v):f$1==="hdr"?await Pe(g.data,$,r):await Fe(g.data,$,r);x=S.bytes,w=S.metadata,await f(b,x),await f(y,`${JSON.stringify(w,null," ")}
2
+ import {d}from'./chunk-7N6TU4JG.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import'./chunk-65VEJRRT.js';import {b,a as a$1,c,h,d as d$1,f}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {readFile,lstat,readdir,realpath,mkdir}from'fs/promises';import i from'path';import {read,KHR_DF_PRIMARIES_BT709,write}from'ktx-parse';var U=2,ie="ktx2-encoder@0.6.0",ae=i.join(".three-blocks","assets"),ue=i.join(ae,"meta.json"),we=i.join(ae,"cache"),Te=256*1024*1024,Ae=64*1024*1024,ee=115e5,te=64,Ee=163,Re=166,ve=167,Se=1000066e3,de=1,le=2,$e=/baseColor|emissive|diffuse|sheenColor|specularColor/u,Me=/normal/iu,Oe=/(?:^|[_\-.])(?:normal|nrm|nor)(?:[_\-.]|map|$)/iu,_e=/(?:rough|metal|orm\b|occlusion|ambient|[_\-.]ao(?:[_\-.]|$)|height|disp|thick|mask)/iu;function Ie(t){return t.some(e=>Me.test(e))?"normal":t.some(e=>$e.test(e))||t.length===0?"color":"data"}a(Ie,"presetForTextureSlots");function De(t){let e=i.basename(t);return Oe.test(e)?"normal":_e.test(e)?"data":"color"}a(De,"presetForImageName");function V(t){let e=i.extname(t).toLowerCase();return e===".glb"?"glb":e===".png"||e===".jpg"||e===".jpeg"||e===".webp"?"image":e===".hdr"?"hdr":null}a(V,"assetKindFor");function P(t,e){let r=i.relative(t,e);return (r!==""&&!r.startsWith("..")&&!i.isAbsolute(r)?r:e).split(i.sep).join("/")}a(P,"portable");var X;function ce(){return X??=Promise.all([import('ktx2-encoder'),import('sharp')]).then(([t,e])=>({encodeToKTX2:t.encodeToKTX2,sharp:e.default})),X}a(ce,"loadEncoderTools");function me(t,e){let r=e.quality==="high";return t==="hdr"?{mode:"uastc-hdr",options:{isHDR:true,imageType:"hdr",isUASTC:true,isYFlip:true,generateMipmap:true,needSupercompression:true,hdrQualityLevel:r?2:1}}:t==="color"&&!r?{mode:"etc1s",options:{isUASTC:false,qualityLevel:160,compressionLevel:2,isPerceptual:true,isSRGB:true,generateMipmap:true}}:{mode:"uastc",options:{isUASTC:true,uastcLDRQualityLevel:r?2:1,enableRDO:true,rdoQualityLevel:1,generateMipmap:true,needSupercompression:true,isPerceptual:t==="color",isSRGB:t==="color",isNormalMap:t==="normal"}}}a(me,"encoderOptionsFor");function Le(t,e){let r=read(t),s=r.dataFormatDescriptor[0];if(s===void 0)return t;let n=e==="color"?le:de;return s.transferFunction===n&&(e!=="color"||s.colorPrimaries===KHR_DF_PRIMARIES_BT709)?t:(s.transferFunction=n,e==="color"&&(s.colorPrimaries=KHR_DF_PRIMARIES_BT709),write(r,{keepWriter:true}))}a(Le,"normalizeDfdTransfer");function he(t,e,r,s){let n=read(t),o=n.dataFormatDescriptor[0];if(o===void 0)throw new Error(`${s} produced a KTX2 container without a data format descriptor.`);if(e==="hdr"){if(n.vkFormat!==Se||o.colorModel!==ve)throw new Error(`${s} is not a UASTC HDR container (vkFormat ${n.vkFormat}, color model ${o.colorModel}).`)}else {let c=r==="etc1s"?Ee:Re;if(n.vkFormat!==0||o.colorModel!==c)throw new Error(`${s} is not a ${r} container (vkFormat ${n.vkFormat}, color model ${o.colorModel}).`)}let a=e==="color",u=o.transferFunction;if(a&&u!==le)throw new Error(`${s} must carry the sRGB transfer function; found ${u}.`);if(!a&&u!==de)throw new Error(`${s} must carry the linear transfer function; found ${u}.`);if(Math.max(n.pixelWidth,n.pixelHeight)>=8&&n.levels.length<2)throw new Error(`${s} is missing its mip chain.`);return {width:n.pixelWidth,height:n.pixelHeight,levels:n.levels.length}}a(he,"verifyKtx2");async function ye(t,e,r,s){let{encodeToKTX2:n,sharp:o}=await ce(),a$1=r.maxDimension,{mode:u,options:c}=me(e,r),d=performance.now(),m=false,p=Le(await n(t,{...c,imageDecoder:a(async $=>{let E=o($),M=await E.metadata(),O=M.width??0,b=M.height??0;if(O<1||b<1)throw new Error(`${s} has no decodable dimensions.`);let y=Math.min(1,a$1/Math.max(O,b));O*y*b*y>ee&&(y=Math.sqrt(ee/(O*b)));let x=y<1,w=x?Math.max(4,Math.floor(O*y/4)*4):O,I=x?Math.max(4,Math.floor(b*y/4)*4):b,_=x?E.resize(w,I,{fit:"fill",kernel:"lanczos3"}):E,{data:h,info:v}=await _.ensureAlpha().raw().toBuffer({resolveWithObject:true});for(let S=3;S<h.byteLength;S+=4)if(h[S]!==255){m=true;break}return {data:new Uint8Array(h.buffer,h.byteOffset,h.byteLength),width:v.width,height:v.height}},"decode")}),e),{width:f,height:R,levels:g}=he(p,e,u,s);return {bytes:p,width:f,height:R,levels:g,hasAlpha:m,mode:u,durationMs:performance.now()-d}}a(ye,"encodeLdrTexture");function Be(t,e){let r=new TextDecoder("latin1").decode(t.subarray(0,Math.min(t.byteLength,4096))),s=/-Y\s+(\d+)\s+\+X\s+(\d+)/u.exec(r);if(s?.[1]===void 0||s[2]===void 0)throw new Error(`${e} is not a supported Radiance .hdr file (missing "-Y <h> +X <w>" resolution).`);return {width:Number(s[2]),height:Number(s[1])}}a(Be,"hdrDimensions");async function ke(t,e,r){let s=Be(t,r);if(Math.max(s.width,s.height)>e.hdrMaxDimension)throw new Error(`${r} is ${s.width}x${s.height}, above the ${e.hdrMaxDimension}px HDR cap; resize the source (HDR resize is not supported yet).`);let{encodeToKTX2:n}=await ce(),{mode:o,options:a}=me("hdr",e),u=performance.now(),c=await n(t,a),{width:d,height:m,levels:A}=he(c,"hdr",o,r);return {bytes:c,width:d,height:m,levels:A,hasAlpha:false,mode:o,durationMs:performance.now()-u}}a(ke,"encodeHdrTexture");function pe(t,e,r,s){let n=0,o=t,a=e;for(let u=0;u<r;u+=1)n+=o*a*s,o=Math.max(1,o>>1),a=Math.max(1,a>>1);return n}a(pe,"uncompressedMipBytes");function q(t,e,r,s){let n=0,o=t,a=e;for(let u=0;u<r;u+=1)n+=Math.ceil(o/4)*Math.ceil(a/4)*s,o=Math.max(1,o>>1),a=Math.max(1,a>>1);return n}a(q,"compressedMipBytes");function fe(t,e){return t==="etc1s"&&!e?8:16}a(fe,"transcodedBlockBytes");async function Fe(t,e,r){let s=r.preset??De(e),n=`Image ${JSON.stringify(i.basename(e))}`,o=await ye(t,s,r,n),a=[`preset ${s} (${r.preset===null?"from filename":"explicit"})`];return s!=="color"&&a.push("linear DFD: consumers must treat this texture as non-color data"),a.push("compressed textures never flip: sample with glTF-style (flipY=false) UVs"),{bytes:o.bytes,metadata:{vramBytesIn:pe(o.width,o.height,o.levels,4),vramBytesOut:q(o.width,o.height,o.levels,fe(o.mode,o.hasAlpha)),textures:[{name:i.basename(e),slots:[],preset:s,mode:o.mode,width:o.width,height:o.height,bytesIn:t.byteLength,bytesOut:o.bytes.byteLength,durationMs:Math.round(o.durationMs)}],notes:a}}}a(Fe,"buildImageAsset");async function Pe(t,e,r){let s=`Environment ${JSON.stringify(i.basename(e))}`,n=await ke(t,r,s);return {bytes:n.bytes,metadata:{vramBytesIn:n.width*n.height*8,vramBytesOut:q(n.width,n.height,n.levels,16),textures:[{name:i.basename(e),slots:["equirectangular"],preset:"hdr",mode:n.mode,width:n.width,height:n.height,bytesIn:t.byteLength,bytesOut:n.bytes.byteLength,durationMs:Math.round(n.durationMs)}],notes:["BC6H on BC-capable devices; transcodes to RGBA16F elsewhere"]}}}a(Pe,"buildHdrAsset");async function Ne(t,e,r,s){let[{Logger:n,NodeIO:o},{ALL_EXTENSIONS:a,KHRTextureBasisu:u},{dedup:c,listTextureSlots:d,meshopt:m,prune:A,weld:p},{MeshoptDecoder:f,MeshoptEncoder:R}]=await Promise.all([import('@gltf-transform/core'),import('@gltf-transform/extensions'),import('@gltf-transform/functions'),import('meshoptimizer')]);await R.ready,await f.ready;let g=new o().registerExtensions(a).registerDependencies({"meshopt.encoder":R,"meshopt.decoder":f}),$=`GLB ${JSON.stringify(i.basename(e))}`;g.setLogger(new n(n.Verbosity.SILENT));let E=await g.readBinary(t);E.setLogger(new n(n.Verbosity.SILENT));let M=E.getRoot().listTextures();if(M.length>0&&M.every(h=>h.getMimeType()==="image/ktx2")&&E.getRoot().listExtensionsUsed().some(h=>h.extensionName==="EXT_meshopt_compression"))return {bytes:t,metadata:{vramBytesIn:0,vramBytesOut:0,textures:[],notes:["already optimized (KTX2 + meshopt); copied unchanged"]}};s?.("optimizing geometry"),await E.transform(c(),A({keepAttributes:true,keepExtras:true,keepSolidTextures:true}),p(),m({encoder:R,level:"medium"}));let b=[],y=[],x=0,w=0,I=0;for(let h of M){let v=h.getName()||h.getURI()||`texture-${b.length}`,S=h.getImage(),k=h.getMimeType();if(S===null||S.byteLength===0)continue;if(k==="image/ktx2"){y.push(`${v}: already KTX2, kept`);continue}if(!/^image\/(?:png|jpeg|webp)$/u.test(k)){y.push(`${v}: unsupported ${k}, kept`);continue}let z=h.getSize();if(z!==null&&Math.max(z[0],z[1])<te){y.push(`${v}: below ${te}px, kept`);continue}let W=d(h),j=Ie(W);s?.(`encoding ${v} (${j})`);let T=await ye(new Uint8Array(S),j,r,`${$} texture ${JSON.stringify(v)}`);h.setImage(T.bytes).setMimeType("image/ktx2");let G=h.getURI();G!==""&&h.setURI(G.replace(/\.(?:png|jpe?g|webp)$/iu,".ktx2")),I+=1,x+=pe(T.width,T.height,T.levels,4),w+=q(T.width,T.height,T.levels,fe(T.mode,T.hasAlpha)),b.push({name:v,slots:W,preset:j,mode:T.mode,width:T.width,height:T.height,bytesIn:S.byteLength,bytesOut:T.bytes.byteLength,durationMs:Math.round(T.durationMs)});}I>0&&E.createExtension(u).setRequired(true);let _=await g.writeBinary(E);return await g.readBinary(_),I>0&&y.push("requires a KTX2-wired loader (three-blocks/assets or GLTFLoader.setKTX2Loader)"),{bytes:_,metadata:{vramBytesIn:x,vramBytesOut:w,textures:b,notes:y}}}a(Ne,"buildGlbAsset");function Ce(t,e,r){let s=i.basename(t,i.extname(t));if(e==="glb"){let n=r===null?i.join(i.dirname(t),`${s}.tb.glb`):i.join(r,`${s}.glb`);if(i.resolve(n)===i.resolve(t))throw new Error(`Output would overwrite the input: ${JSON.stringify(t)}. Pass a different output directory.`);return n}return i.join(r??i.dirname(t),`${s}.ktx2`)}a(Ce,"outputPathFor");async function ge(t){let e={schemaVersion:U,tool:{name:"three-blocks-devtools",assetOptimizeVersion:U,encoder:ie},assets:{}},r;try{r=await readFile(t,"utf8");}catch(s){if(b(s)==="ENOENT")return e;throw s}if(r.length>a$1.receipt)return e;try{let s=JSON.parse(r);if(typeof s!="object"||s===null)return e;let n=s;return n.schemaVersion!==U||typeof n.assets!="object"||n.assets===null?e:{...e,assets:{...n.assets}}}catch{return e}}a(ge,"readReceipt");async function Ue(t){let e=[];for(let r of t){let s=i.resolve(r);if((await lstat(s)).isDirectory()){let o=[s],a=0;for(;o.length>0;){let u=o.shift();if(u===void 0)break;let c=(await readdir(u,{withFileTypes:true})).sort((d,m)=>d.name.localeCompare(m.name));for(let d of c){if(a+=1,a>8192)throw new Error("Input directory expansion exceeds the 8192-entry limit.");if(d.isSymbolicLink()||d.name.startsWith("."))continue;let m=i.join(u,d.name);if(d.isDirectory()){d.name!=="three-blocks"&&o.push(m);continue}d.isFile()&&!d.name.endsWith(".tb.glb")&&V(d.name)!==null&&e.push(m);}}}else e.push(s);}if(e.length===0)throw new Error("No optimizable inputs found (.glb, .png, .jpg, .webp, .hdr).");return e}a(Ue,"expandInputs");async function Ve(t){let e=await realpath(t.root),r={maxDimension:re(t.maxDimension,2048),hdrMaxDimension:re(t.hdrMaxDimension,4096),quality:t.quality??"default",preset:t.preset??null},s=t.outDir===void 0?null:i.resolve(e,t.outDir);s!==null&&await mkdir(s,{recursive:true});let n=i.join(e,we),o=i.join(e,ue),a$2=c(d({version:U,encoder:ie,...r})),u=await Ue(t.inputs),c$1=[],d$2=[],m=await ge(o);for(let[A,p]of u.entries()){let f$1=V(p);try{if(f$1===null)throw new Error(`Unsupported asset type ${JSON.stringify(i.extname(p))}; expected .glb, .png, .jpg, .webp, or .hdr (EXR sources are not supported yet \u2014 convert environments to .hdr).`);t.onProgress?.(`${i.basename(p)} (${A+1}/${u.length})`);let R=f$1==="glb"?Te:f$1==="hdr"?Ae:a$1.texture,g=await h(p,R,"Asset input"),$=g.path,E=c(g.data),M=c(`${E}\0${a$2}`),O=f$1==="glb"?"glb":"ktx2",b=i.join(n,`${M}.${O}`),y=i.join(n,`${M}.json`),x,w,I=!1;if(t.force!==!0&&await d$1(b)&&await d$1(y))x=(await h(b,R,"Cached asset")).data,w=JSON.parse((await h(y,a$1.metadata,"Cached asset metadata")).data.toString("utf8")),I=!0;else {let v=a(k=>t.onProgress?.(`${i.basename(p)}: ${k}`),"progress"),S=f$1==="glb"?await Ne(g.data,$,r,v):f$1==="hdr"?await Pe(g.data,$,r):await Fe(g.data,$,r);x=S.bytes,w=S.metadata,await f(b,x),await f(y,`${JSON.stringify(w,null," ")}
3
3
  `);}let _=Ce($,f$1,s);await mkdir(i.dirname(_),{recursive:!0}),await f(_,x);let h$1=c(x);m.assets[P(e,$)]={kind:f$1,inputSha256:E,output:P(e,_),outputSha256:h$1,settingsSha256:a$2,bytesIn:g.data.byteLength,bytesOut:x.byteLength,vramBytesIn:w.vramBytesIn,vramBytesOut:w.vramBytesOut},c$1.push({input:P(e,$),output:P(e,_),kind:f$1,cached:I,bytesIn:g.data.byteLength,bytesOut:x.byteLength,vramBytesIn:w.vramBytesIn,vramBytesOut:w.vramBytesOut,textures:w.textures,notes:w.notes});}catch(R){d$2.push({input:P(e,p),error:R instanceof Error?R.message:String(R)});}}return c$1.length>0&&await f(o,`${JSON.stringify(m,null," ")}
4
4
  `),{schemaVersion:1,command:"assets optimize",root:e,results:c$1,failed:d$2,bytesIn:c$1.reduce((A,p)=>A+p.bytesIn,0),bytesOut:c$1.reduce((A,p)=>A+p.bytesOut,0)}}a(Ve,"optimizeAssets");function re(t,e){if(t===void 0)return e;if(!Number.isInteger(t)||t<64||t>16384)throw new Error("Texture dimension caps must be integers between 64 and 16384.");return t}a(re,"boundedDimension");function D(t){if(t<1e3)return `${t} B`;if(t<1e6){let r=t/1e3;return `${r>=100?Math.round(r):r.toFixed(1)} kB`}let e=t/1e6;return `${e>=100?Math.round(e):e.toFixed(2)} MB`}a(D,"formatBytes");function ne(t,e){if(t===0)return "";let r=Math.round((e-t)/t*100);return r===0?"":` (${r>0?"+":""}${r}%)`}a(ne,"percentDelta");function qe(t){let e=[];for(let r of t.results){let s=r.cached?" \xB7 cached":"";e.push(`${r.input} -> ${r.output}`),e.push(` ${D(r.bytesIn)} -> ${D(r.bytesOut)}${ne(r.bytesIn,r.bytesOut)}${s}`),r.vramBytesOut>0&&e.push(` VRAM \u2248 ${D(r.vramBytesIn)} -> ${D(r.vramBytesOut)}`);for(let n of r.textures){let o=n.slots.length>0?` [${n.slots.join(", ")}]`:"";e.push(` ${n.name}${o} ${n.preset}/${n.mode} ${n.width}x${n.height} ${D(n.bytesIn)} -> ${D(n.bytesOut)}`);}for(let n of r.notes)e.push(` note: ${n}`);}for(let r of t.failed)e.push(`failed ${r.input}: ${r.error}`);return t.results.length>1&&e.push(`total ${D(t.bytesIn)} -> ${D(t.bytesOut)}${ne(t.bytesIn,t.bytesOut)}`),e.join(`
5
5
  `)}a(qe,"formatAssetOptimizeReport");async function We(t,e){let r=await realpath(t),s=i.resolve(r,e);if(!await d$1(s))return [];let n=[],o=[s],a=0;for(;o.length>0;){let u=o.shift();if(u===void 0)break;let c=(await readdir(u,{withFileTypes:true})).sort((d,m)=>d.name.localeCompare(m.name));for(let d of c){if(a+=1,a>8192)throw new Error("Public asset discovery exceeds the 8192-entry limit.");if(d.isSymbolicLink()||d.name.startsWith("."))continue;let m=i.join(u,d.name);if(d.isDirectory()){if(u===s&&d.name==="three-blocks")continue;o.push(m);continue}if(!d.isFile()||d.name.endsWith(".tb.glb"))continue;let A=V(d.name);(A==="glb"||A==="hdr")&&n.push(m);}}return n.sort()}a(We,"discoverPublicAssets");async function Ge(t){let e=await realpath(t),r=await ge(i.join(e,ue)),s=[];for(let[n,o]of Object.entries(r.assets).sort(([a],[u])=>a.localeCompare(u))){let a=i.resolve(e,n),u=i.resolve(e,o.output),c$1="fresh";if(!await d$1(a))c$1="missing-input";else if(!await d$1(u))c$1="missing-output";else {let[d,m]=await Promise.all([readFile(a),readFile(u)]);(c(d)!==o.inputSha256||c(m)!==o.outputSha256)&&(c$1="stale");}s.push({input:n,output:o.output,kind:o.kind,state:c$1});}return {schemaVersion:1,command:"assets status",root:e,state:s.length===0?"empty":s.every(n=>n.state==="fresh")?"fresh":"stale",entries:s}}a(Ge,"inspectAssets");function Je(t){if(t.state==="empty")return "No optimized assets recorded. Run `assets optimize <file|directory>` first.";let e=t.entries.map(r=>`${r.state==="fresh"?"fresh ":r.state.padEnd(14)} ${r.input} -> ${r.output}`);return t.state==="stale"&&e.push("Some assets moved or changed; re-run `assets optimize` on the stale inputs."),e.join(`
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {b,a as a$3}from'./chunk-63ZHTNKQ.js';import'./chunk-IILE5RBI.js';import'./chunk-X5OFYHIY.js';import'./chunk-2TSMAC6E.js';import'./chunk-S22OSG76.js';import'./chunk-EE64MV27.js';import {a as a$2,b as b$1,d}from'./chunk-QJFPNM6W.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import {a as a$1}from'./chunk-65VEJRRT.js';import {j,a as a$4,c}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {randomUUID}from'crypto';import {mkdir,realpath,writeFile,rename,rm}from'fs/promises';import F from'path';import {PNG}from'pngjs';var ye="virtual:three-blocks-devtools/browser-smoke",ve=`\0${ye}`,Ke=`/@id/__x00__${ye}`,Be=9e4;async function Ee(){try{let[e,r]=await Promise.all([import('playwright'),import('vite')]);return {chromium:e.chromium,vite:r}}catch(e){throw new Error('Browser smoke and preview require the optional "playwright" and "vite" packages. Install both in the project and run `npx playwright install chromium`.',{cause:e})}}a(Ee,"loadBrowserSmokeTools");function V(e,r,o,t,n){let a=e??n;if(!Number.isSafeInteger(a)||a<o||a>t)throw new Error(`${r} must be an integer in ${o}...${t}.`);return a}a(V,"boundedInteger");function _e(e,r,o,t,n){let a=e??n;if(!Number.isFinite(a)||a<o||a>t)throw new Error(`${r} must be a finite number in ${o}...${t}.`);return a}a(_e,"boundedRatio");function Pe(e){let r=e??"/";if(r.length===0||r.length>2048||/[\u0000-\u001f\u007f]/u.test(r))throw new Error("Browser smoke route must be a bounded project URL.");let o=new URL(r,"http://three-blocks.invalid/");if(o.origin!=="http://three-blocks.invalid"||o.hash.length>0)throw new Error("Browser smoke route must stay within the project and have no fragment.");return `${o.pathname}${o.search}`}a(Pe,"safeRoute");function N(e,r){return e[r]===true}a(N,"booleanField");function $(e,r){if(!a$1(e)||!a$1(e.value))return {source:"missing",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:r,textReady:!r,firstFrame:false};let o=e.value,t=e.source==="public";if(t&&o.protocolVersion!==1)return {source:"public",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:r,textReady:!r,firstFrame:false};let n=a$1(o.readiness)?o.readiness:o,a=o.worker,d=t&&a$1(a)?a.offscreenCanvas===true&&a.visible===true:a===true;return {source:t?"public":"legacy",backend:t&&a$1(a)?a.offscreenCanvas===true?"OffscreenCanvas":"MainThread":a===true?"OffscreenCanvas":"unknown",worker:d,workerReady:N(n,"workerReady"),assetsReady:N(n,"assetsReady")||N(n,"loadEnd"),compileEnd:N(n,"compileEnd"),textEnabled:r,textReady:!r||N(n,"textReady"),firstFrame:N(n,"firstFrame")}}a($,"parseBrowserSmokeLifecycle");function ie(e){let r=PNG.sync.read(e),o=Math.floor(r.width*.25),t=Math.floor(r.width*.75),n=Math.floor(r.height*.25),a=Math.floor(r.height*.75),d=0,c=0;for(let f=n;f<a;f+=2)for(let p=o;p<t;p+=2){let h=(f*r.width+p)*4,l=r.data[h],i=r.data[h+1],s=r.data[h+2];l===void 0||i===void 0||s===void 0||(d+=Math.max(l,i,s),c+=1);}return c===0?0:d/c}a(ie,"screenshotLuminance");function Je(){return `
2
+ import {b,a as a$3}from'./chunk-ZZLAZ7GJ.js';import'./chunk-IILE5RBI.js';import'./chunk-X5OFYHIY.js';import'./chunk-LKXY5YU2.js';import'./chunk-5FT6AZD6.js';import'./chunk-7N6TU4JG.js';import {a as a$2,b as b$1,d}from'./chunk-QJFPNM6W.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import {a as a$1}from'./chunk-65VEJRRT.js';import {j,a as a$4,c}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {randomUUID}from'crypto';import {mkdir,realpath,writeFile,rename,rm}from'fs/promises';import F from'path';import {PNG}from'pngjs';var ye="virtual:three-blocks-devtools/browser-smoke",ve=`\0${ye}`,Ke=`/@id/__x00__${ye}`,Be=9e4;async function Ee(){try{let[e,r]=await Promise.all([import('playwright'),import('vite')]);return {chromium:e.chromium,vite:r}}catch(e){throw new Error('Browser smoke and preview require the optional "playwright" and "vite" packages. Install both in the project and run `npx playwright install chromium`.',{cause:e})}}a(Ee,"loadBrowserSmokeTools");function V(e,r,o,t,n){let a=e??n;if(!Number.isSafeInteger(a)||a<o||a>t)throw new Error(`${r} must be an integer in ${o}...${t}.`);return a}a(V,"boundedInteger");function _e(e,r,o,t,n){let a=e??n;if(!Number.isFinite(a)||a<o||a>t)throw new Error(`${r} must be a finite number in ${o}...${t}.`);return a}a(_e,"boundedRatio");function Pe(e){let r=e??"/";if(r.length===0||r.length>2048||/[\u0000-\u001f\u007f]/u.test(r))throw new Error("Browser smoke route must be a bounded project URL.");let o=new URL(r,"http://three-blocks.invalid/");if(o.origin!=="http://three-blocks.invalid"||o.hash.length>0)throw new Error("Browser smoke route must stay within the project and have no fragment.");return `${o.pathname}${o.search}`}a(Pe,"safeRoute");function N(e,r){return e[r]===true}a(N,"booleanField");function $(e,r){if(!a$1(e)||!a$1(e.value))return {source:"missing",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:r,textReady:!r,firstFrame:false};let o=e.value,t=e.source==="public";if(t&&o.protocolVersion!==1)return {source:"public",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:r,textReady:!r,firstFrame:false};let n=a$1(o.readiness)?o.readiness:o,a=o.worker,d=t&&a$1(a)?a.offscreenCanvas===true&&a.visible===true:a===true;return {source:t?"public":"legacy",backend:t&&a$1(a)?a.offscreenCanvas===true?"OffscreenCanvas":"MainThread":a===true?"OffscreenCanvas":"unknown",worker:d,workerReady:N(n,"workerReady"),assetsReady:N(n,"assetsReady")||N(n,"loadEnd"),compileEnd:N(n,"compileEnd"),textEnabled:r,textReady:!r||N(n,"textReady"),firstFrame:N(n,"firstFrame")}}a($,"parseBrowserSmokeLifecycle");function ie(e){let r=PNG.sync.read(e),o=Math.floor(r.width*.25),t=Math.floor(r.width*.75),n=Math.floor(r.height*.25),a=Math.floor(r.height*.75),d=0,c=0;for(let f=n;f<a;f+=2)for(let p=o;p<t;p+=2){let h=(f*r.width+p)*4,l=r.data[h],i=r.data[h+1],s=r.data[h+2];l===void 0||i===void 0||s===void 0||(d+=Math.max(l,i,s),c+=1);}return c===0?0:d/c}a(ie,"screenshotLuminance");function Je(){return `
3
3
  import * as THREE from 'three/webgpu';
4
4
  import { createAssetLoaderRegistry, createAssetManager, createThreeAssetAdapters, defineAssets } from 'three-blocks/assets';
5
5
  import { SceneHotReloader } from 'three-blocks/hmr';
@@ -0,0 +1,80 @@
1
+ import {d,a as a$1,X,z,Y,B,U,m,l,h,g,S}from'./chunk-NF4RFSUJ.js';import {a}from'./chunk-EI7MMDWY.js';import x from'process';import {createServer}from'http';import {createRequire}from'module';import {mkdtemp,rm,lstat,realpath}from'fs/promises';import A from'path';import {tmpdir}from'os';import {pathToFileURL}from'url';var Le=Object.freeze([{id:"three-inspector-invalid-json",pattern:/is not valid JSON/iu},{id:"chromium-webgpu-experimental",pattern:/WebGPU is experimental/iu},{id:"browser-automatic-favicon",pattern:/Failed to load resource:.*404.*\/favicon\.ico/iu}]);function Z(n){return Le.some(e=>e.pattern.test(n))}a(Z,"isDocumentedBrowserNoise");function fe(n=x.env,e=x.platform){let t=n.THREE_BLOCKS_WEBGPU_BROWSER_ARGS?.split(/\s+/u).filter(Boolean);if(t&&t.length>0)return t;let r=["--enable-unsafe-webgpu"];return e==="darwin"&&r.push("--enable-gpu","--use-angle=metal"),e==="linux"&&r.push("--enable-features=Vulkan","--disable-vulkan-surface","--ignore-gpu-blocklist","--disable-gpu-driver-bug-workarounds","--disable-gpu-watchdog"),r}a(fe,"webgpuBrowserArgs");function pe(n=x.env){let e=n.THREE_BLOCKS_WEBGL_BROWSER_ARGS?.split(/\s+/u).filter(Boolean);return e&&e.length>0?e:["--use-angle=swiftshader","--enable-unsafe-swiftshader","--ignore-gpu-blocklist"]}a(pe,"webglBrowserArgs");function we(n=false,e=x.env){return n!==true&&e.THREE_BLOCKS_SOFTWARE_WEBGPU!=="1"}a(we,"webgpuBrowserHeadless");var ee="three-blocks.shader-capture.runtime.v1";var Re="/__three-blocks/shaders/capture",K="/__three-blocks/shaders/telemetry",Te="/__three-blocks/shaders/runtime.js",ke="/__three-blocks/shaders/bootstrap.js",Ee="/__three-blocks/shaders/bridge.js",Pe=d.manifest*2,ne=/^[a-z0-9][a-z0-9_-]{0,63}$/u,Ce=64,Be=3e4;async function Ve(){try{return (await import('playwright')).chromium}catch(n){throw new Error('Shader browser work requires the optional "playwright" package. Install it in the project and run `npx playwright install chromium`.',{cause:n})}}a(Ve,"loadChromium");async function We(n){let e;try{e=createRequire(A.join(n,"package.json")).resolve("vite");}catch(r){throw new Error("Shader capture requires Vite in the target project.",{cause:r})}let t=await import(pathToFileURL(e).href);if(typeof t.createServer!="function")throw new Error(`The target project's Vite entry does not export createServer(): ${e}`);return t.createServer}a(We,"loadProjectCreateServer");var ae=class{static{a(this,"CaptureInbox");}#e=new Map;#t=new Map;wait(e,t){let r=this.#t.get(e);if(r!==void 0)return this.#t.delete(e),Promise.resolve(r);if(this.#e.has(e))throw new Error(`A shader capture is already waiting for scene "${e}".`);return new Promise((a,s)=>{let o=setTimeout(()=>{this.#e.delete(e),s(new Error(`Shader capture "${e}" timed out after ${t}ms.`));},t);this.#e.set(e,{resolve:a,reject:s,timer:o});})}receive(e){if(!a$1(e)||typeof e.scene!="string"||!ne.test(e.scene))throw new Error("Capture POST has no safe scene key.");if(!this.#t.has(e.scene)&&!this.#e.has(e.scene)&&this.#t.size>=Ce)throw new Error("Capture POST exceeds the scene inbox limit.");let t=this.#e.get(e.scene);t?(clearTimeout(t.timer),this.#e.delete(e.scene),t.resolve(e)):this.#t.set(e.scene,e);}cancel(e,t){let r=this.#e.get(e);r&&(clearTimeout(r.timer),this.#e.delete(e),r.reject(t));}rejectAll(e){for(let t of this.#e.values())clearTimeout(t.timer),t.reject(e);this.#e.clear(),this.#t.clear();}};async function Je(n,e){let t=await Promise.race([e.then(r=>({kind:"capture",value:r})),n.then(()=>({kind:"navigation"}))]);return t.kind==="capture"?t.value:e}a(Je,"waitForShaderCaptureAcrossNavigation");var oe=class{static{a(this,"TelemetryHub");}#e=new Map;#t=new Map;markFirstRequest(e){ne.test(e)&&!this.#t.has(e)&&this.#t.set(e,Date.now());}firstRequest(e){return this.#t.get(e)}receive(e){if(!a$1(e)||typeof e.scene!="string"||!ne.test(e.scene))throw new Error("Shader telemetry has no bounded scene key.");if(!this.#e.has(e.scene)&&this.#e.size>=Ce)throw new Error("Shader telemetry exceeds the scene limit.");this.#e.set(e.scene,e);}read(e){return this.#e.get(e)}clear(e){this.#e.delete(e),this.#t.delete(e);}},Ke=a(async(n,e,t,r,a)=>{let s=0;for(;n.__threeBlocksParityUsesAnimationLoop!==true&&s<e;)await r(),s+=1;if(n.__threeBlocksParityUsesAnimationLoop===true){let o=Number(n.__threeBlocksParityCompletedFrame||0),i=Number(t),d=Number.isSafeInteger(i)&&i>=o?i:o+e;for(n.__threeBlocksParityTargetFrame=d;Number(n.__threeBlocksParityCompletedFrame||0)<d;)await r();}return await a(),Number(n.__threeBlocksParityCompletedFrame||0)},"settleShaderParityFrames");function se(n,e){return `(() => {
2
+ const root = globalThis;
3
+ const scene = new URL(location.href).searchParams.get('captureId')
4
+ || 'default';
5
+ const workerCapture = ${JSON.stringify(e??null).replaceAll("<","\\u003c")};
6
+ if (workerCapture) root[Symbol.for('three-blocks.shader-capture.worker-activation.v1')] = { ...workerCapture, scene };
7
+ const randomSeed = (value) => {
8
+ let state = 2166136261;
9
+ for (let index = 0; index < value.length; index++) state = Math.imul(state ^ value.charCodeAt(index), 16777619) >>> 0;
10
+ return state === 0 ? 0x9e3779b9 : state;
11
+ };
12
+ const advanceRandom = (state) => {
13
+ state ^= state << 13;
14
+ state ^= state >>> 17;
15
+ state ^= state << 5;
16
+ return state >>> 0;
17
+ };
18
+ const parityMode = new URL(location.href).searchParams.get('threeBlocksShaderMode');
19
+ if (parityMode === 'live' || parityMode === 'precompiled') {
20
+ root.__threeBlocksParityEpoch = 1700000000000;
21
+ root.__threeBlocksParityTime = 0;
22
+ Date.now = () => root.__threeBlocksParityEpoch + Number(root.__threeBlocksParityTime || 0);
23
+ }
24
+ const randomStreams = new Map();
25
+ Math.random = () => {
26
+ const stackLine = String(new Error().stack || '').split('\\n')[2] || 'unknown';
27
+ const originIndex = stackLine.indexOf(location.origin);
28
+ const callsite = (originIndex >= 0 ? stackLine.slice(0, originIndex) : stackLine).trim() || 'anonymous';
29
+ const next = advanceRandom(randomStreams.get(callsite) ?? randomSeed(scene + '|' + callsite));
30
+ randomStreams.set(callsite, next);
31
+ return next / 4294967296;
32
+ };
33
+ const readiness = { workerReady: false, assetsReady: false, textReady: false, compileEnd: false, firstFrame: false };
34
+ const stats = { buildCalls: 0, renderBuilds: 0, computeBuilds: 0, registeredBuilds: 0, registeredRenderBuilds: 0, registeredComputeBuilds: 0, buildMs: 0, syncBuildMs: 0, asyncBuildElapsedMs: 0, precompiledSetupMs: 0, maxSyncBuildMs: 0, maxPrecompiledSetupMs: 0, hydrationMs: 0, maxHydrationMs: 0, injected: 0, injectedRender: 0, injectedCompute: 0, missed: 0, missedRender: 0, missedCompute: 0, missedKeys: [] };
35
+ const settleParityFrames = ${Ke.toString()};
36
+ const settle = (frames, requestedTarget) => settleParityFrames(
37
+ root,
38
+ frames,
39
+ requestedTarget,
40
+ () => new Promise((resolve) => requestAnimationFrame(resolve)),
41
+ () => new Promise((resolve) => setTimeout(resolve, 100)),
42
+ );
43
+ const bridge = { protocolVersion: 1, compatibility: ${JSON.stringify(n)}, transform: ${B}, readiness, stats, settle };
44
+ root.__threeBlocksShaderTools = bridge;
45
+ requestAnimationFrame(() => requestAnimationFrame(() => { readiness.firstFrame = true; }));
46
+ const poll = async () => {
47
+ try {
48
+ const response = await fetch('/__three-blocks/shaders/telemetry?scene=' + encodeURIComponent(scene), { cache: 'no-store' });
49
+ if (response.status !== 204 && response.ok) {
50
+ const payload = await response.json();
51
+ if (payload.protocolVersion !== 1 || payload.compatibility !== bridge.compatibility || payload.transform !== bridge.transform) throw new Error('incompatible shader telemetry');
52
+ Object.assign(stats, payload.stats);
53
+ if (Array.isArray(payload.demands)) bridge.demands = payload.demands;
54
+ if (typeof payload.demandTotal === 'number') bridge.demandTotal = payload.demandTotal;
55
+ readiness.workerReady = true;
56
+ if (payload.settled === true) {
57
+ readiness.assetsReady = true;
58
+ readiness.textReady = true;
59
+ readiness.compileEnd = true;
60
+ }
61
+ const smoke = root.__threeBlocksSmoke && typeof root.__threeBlocksSmoke === 'object' ? root.__threeBlocksSmoke : { protocolVersion: 1, worker: { offscreenCanvas: true, visible: true }, readiness: {} };
62
+ smoke.readiness = { ...(smoke.readiness || {}), ...readiness };
63
+ root.__threeBlocksSmoke = smoke;
64
+ }
65
+ } catch {}
66
+ setTimeout(poll, 40);
67
+ };
68
+ void poll();
69
+ })();`}a(se,"publicBridgeScript");function _e(n,e,t,r,a=false){let s=new URL(n.url??"/","http://three-blocks.invalid"),o=s.pathname;if(a&&n.method==="GET"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.(?:webgpu|webgl)\.json$/u.test(o))return e.statusCode=204,e.end(),true;if(o===K&&n.method==="GET"){let h=s.searchParams.get("scene")??"",S=r.read(h);return S===void 0?(e.statusCode=204,e.end()):(e.statusCode=200,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify(S))),true}let i=o===Re,d=o===K;if(!i&&!d)return false;if(n.method!=="POST")return e.statusCode=405,e.end("POST required"),true;let u=[],f=0,p=false;return n.on("data",h=>{f+=h.byteLength,f>Pe?p=true:u.push(h);}),n.on("end",()=>{if(p){e.statusCode=413,e.end("capture payload too large");return}try{let h=JSON.parse(Buffer.concat(u).toString("utf8"));d?r.receive(h):t.receive(h),e.statusCode=204,e.end();}catch(h){e.statusCode=400,e.end(h instanceof Error?h.message:String(h));}}),true}a(_e,"handleCaptureEndpoint");function qe(n,e,t,r,a){return {name:"three-blocks:shader-capture-endpoint",transformIndexHtml(){return [{tag:"script",children:se(r,a),injectTo:"head-prepend"}]},configureServer(s){s.middlewares.use((o,i,d)=>{let f=new URL(o.url??"/","http://three-blocks.invalid").searchParams.get("captureId");f!==null&&e.markFirstRequest(f),!_e(o,i,n,e,t)&&d();});}}}a(qe,"captureEndpointPlugin");function ge(n,e,t){let r=new URL(e.url,n);for(let[a,s]of Object.entries(t))r.searchParams.set(a,s);return r.href}a(ge,"browserUrl");function ze(n,e,t){let r=new URL(e.url,n);for(let a of ["capture","precompiled"])r.searchParams.delete(a);return r.searchParams.set("captureId",e.key),r.searchParams.set("threeBlocksShaderCapture","1"),r.searchParams.set("threeBlocksShaderMode","precompiled"),t==="webgl"&&r.searchParams.set("webgl","1"),r.searchParams.set("tbStats","1"),r.href}a(ze,"publishedBrowserUrl");async function M(n){let e;try{await Promise.race([n(),new Promise(t=>{e=setTimeout(t,Be);})]);}catch{}finally{e&&clearTimeout(e);}}a(M,"closeBrowserResource");async function J(n){let e;try{return await Promise.race([n().catch(()=>null),new Promise(t=>{e=setTimeout(()=>t(null),Be);})])}finally{e!==void 0&&clearTimeout(e);}}a(J,"readPageDiagnostic");function te(n){let e=a(()=>{},"resolveFirst"),t=new Promise(u=>{e=u;}),r=a(()=>{},"removeBrowserListener"),a$1={console:[],page:[],first:t,dispose:a(()=>r(),"dispose")},s=false,o=a(u=>{s||(s=true,e(new Error(u)));},"report"),i=n.context().browser(),d=a(()=>o("Shader browser disconnected before observation completed."),"onDisconnected");return i?.on("disconnected",d),r=a(()=>{i?.off("disconnected",d);},"removeBrowserListener"),n.on("console",u=>{let f=u.type()==="warning"&&/\[three-blocks\/shaders\].*(?:has no entry|manifest miss|hydration)/iu.test(u.text());if(u.type()!=="error"&&!f||Z(u.text()))return;let p=u.location().url,h=p.length>0?`${u.text()} (${p})`:u.text();a$1.console.push(h),o(`Browser console ${f?"warning":"error"}: ${h}`);}),n.on("pageerror",u=>{if(Z(u.message))return;let f=u.stack||u.message;a$1.page.push(f),o(`Browser page error: ${f}`);}),n.on("crash",()=>o("Browser page crashed before shader capture completed.")),n.on("close",()=>o("Browser page closed before shader capture completed.")),a$1}a(te,"collectErrors");function L(n,e,t=false){return typeof n[e]=="boolean"?n[e]:t}a(L,"booleanField");function Ye(n){if(!a$1(n))throw new Error("Browser shader stats are unavailable.");let e=a((t,r=true)=>{let a=n[t];if(typeof a!="number"||!Number.isFinite(a)||a<0||r&&!Number.isSafeInteger(a))throw new Error(`Browser shader stats.${t} is invalid.`);return a},"read");return {buildCalls:e("buildCalls"),renderBuilds:e("renderBuilds"),computeBuilds:e("computeBuilds"),registeredBuilds:e("registeredBuilds"),registeredRenderBuilds:e("registeredRenderBuilds"),registeredComputeBuilds:e("registeredComputeBuilds"),buildMs:e("buildMs",false),syncBuildMs:e("syncBuildMs",false),asyncBuildElapsedMs:e("asyncBuildElapsedMs",false),precompiledSetupMs:e("precompiledSetupMs",false),maxSyncBuildMs:e("maxSyncBuildMs",false),maxPrecompiledSetupMs:e("maxPrecompiledSetupMs",false),hydrationMs:e("hydrationMs",false),maxHydrationMs:e("maxHydrationMs",false),injected:e("injected"),injectedRender:e("injectedRender"),injectedCompute:e("injectedCompute"),missed:e("missed"),missedRender:e("missedRender"),missedCompute:e("missedCompute"),...Array.isArray(n.missedKeys)&&n.missedKeys.every(t=>typeof t=="string")?{missedKeys:n.missedKeys}:{}}}a(Ye,"parseStats");function V(n,e,t,r,a){if(!a$1(n))throw new Error("The page did not expose the public shader devtools bridge.");if(!t&&n.protocolVersion!==1)throw new Error(`Scene "${e.key}" exposed an unsupported shader bridge protocol.`);let s=n.readiness;if(!a$1(s))throw new Error("The shader bridge readiness snapshot is invalid.");let o={workerReady:L(s,"workerReady"),assetsReady:L(s,"assetsReady"),textReady:e.requiresText?L(s,"textReady"):true,compileEnd:L(s,"compileEnd"),firstFrame:L(s,"firstFrame",t)};if(!o.workerReady||!o.assetsReady||!o.textReady||!o.compileEnd)throw new Error(`Scene "${e.key}" did not reach worker/assets/text/compile readiness.`);let i=t?a:n.compatibility,d=t?B:n.transform;if(i!==a||d!==B)throw new Error(`Scene "${e.key}" exposed incompatible shader bridge metadata.`);Y(r);let u=Array.isArray(n.demands)?n.demands.filter(a$1).slice(0,64):void 0;return {compatibility:a,transform:d,readiness:o,stats:Ye(n.stats),...u===void 0?{}:{demands:u}}}a(V,"parseBridge");async function W(n,e){return n.evaluate(t=>{let r=globalThis;if(!t)return r.__threeBlocksShaderTools??null;let a=r.__threeBlocks,s=r.__threeBlocksTslStats;if(!a||typeof a!="object")return null;let o=a;return {readiness:{workerReady:o.workerReady===true,assetsReady:o.loadEnd===true||o.assetsReady===true,textReady:o.textReady===true,compileEnd:o.compileEnd===true,firstFrame:true},stats:s}},e)}a(W,"readBridge");async function xe(n,e){let t=await J(()=>n.evaluate(r=>{let a$1=globalThis,s=a(i=>{let d=a$1;for(let u of i.split(".")){if(d===null||typeof d!="object"&&typeof d!="function")return;d=Reflect.get(d,u);}return d},"resolveGlobal"),o=null;if(r!==null)try{o=JSON.stringify(s(`${r}Diagnostics`))??null;}catch{o=null;}return JSON.stringify({parityCompletedFrame:Number(a$1.__threeBlocksParityCompletedFrame??0),diagnostics:o})},e??null));return t===null?{alive:false,signature:""}:{alive:true,signature:t}}a(xe,"probePageProgress");async function F(n,e,t,r){let a$1=n.evaluate(async u=>{let p=globalThis.__threeBlocksShaderTools;if(p&&typeof p=="object"){let g=Reflect.get(p,"settle");if(typeof g=="function"){let c=await g(u.frames,u.targetFrame);return typeof c=="number"&&Number.isSafeInteger(c)?c:0}}if(!u.legacy||!u.modulePath)throw new Error("The public shader bridge does not provide deterministic settle().");let h=await import(u.modulePath);if(!h.store||typeof h.store!="object")throw new Error("Legacy deterministic store is unavailable.");let S=h.store;return S.recordFrameCount=0,S.recordFrameRate=60,S.recordTotalFrames=u.frames,S.recording=true,await new Promise((g,c)=>{let w=Date.now(),m=a(()=>{if(S.recording===false)return g();if(Date.now()-w>u.timeoutMs)return c(new Error("Legacy deterministic settle timed out."));setTimeout(m,25);},"poll");m();}),0},{frames:t,targetFrame:r,legacy:e.bridge.legacyLab,modulePath:e.bridge.deterministicModule??null,timeoutMs:e.timeoutMs}),s=j(e),o=false,i,d=(async()=>{let u=Date.now(),f=u,p="";for(;;){let h=s-(Date.now()-u);if(h<=0)throw new Error(`Shader parity settle timed out after ${s}ms.`);let S=e.timeoutMs-(Date.now()-f);if(S<=0){let g=await xe(n,e.readiness.global);if(o)throw new Error("Shader parity settle already resolved.");if(g.alive&&g.signature===p)throw new Error(`Shader parity settle timed out after ${e.timeoutMs}ms without progress (hard cap ${s}ms).`);p=g.signature,f=Date.now();continue}if(await new Promise(g=>{i=setTimeout(g,Math.min(S,h,2500));}),o)throw new Error("Shader parity settle already resolved.")}})();try{return await Promise.race([a$1,d])}finally{o=true,i!==void 0&&clearTimeout(i),d.catch(()=>{});}}a(F,"settlePage");async function Se(n,e,t){e.readiness.selector===void 0&&e.readiness.global===void 0||await Promise.race([n.waitForFunction(r=>{let a=globalThis;if(r.selector!==void 0&&a.document?.querySelector(r.selector)==null)return false;if(r.global===void 0)return true;let s=a;for(let d of r.global.split(".")){if((typeof s!="object"||s===null)&&typeof s!="function")return false;s=Reflect.get(s,d);}if(s===true)return true;if(typeof s!="object"||s===null||typeof Reflect.get(s,"then")!="function")return false;let o=a.__threeBlocksReadinessState,i=o instanceof Map?o:new Map;return o instanceof Map||(a.__threeBlocksReadinessState=i),i.has(s)||(i.set(s,false),Promise.resolve(s).then(()=>i.set(s,true),()=>i.set(s,false))),i.get(s)===true},e.readiness,{timeout:j(e)}),t.first.then(r=>Promise.reject(r))]);}a(Se,"waitForConfiguredReadiness");async function be(n){let e=n.locator("canvas"),r=(await e.evaluateAll(a=>a.map((s,o)=>{let i=s.getBoundingClientRect();return {index:o,area:Math.max(0,i.width)*Math.max(0,i.height)}}))).sort((a,s)=>s.area-a.area)[0];if(r===void 0||r.area<=0)throw new Error("Published page has no visible renderer canvas.");return Buffer.from(await e.nth(r.index).screenshot({type:"png"}))}a(be,"primaryCanvasScreenshot");async function re(n,e,t,r,a,s,o){let i=q(r,a,s),d=await U(),u=`(() => {
70
+ const runtime = globalThis[Symbol.for(${JSON.stringify(ee)})];
71
+ if (!runtime || typeof runtime.configureThreeBlocksShaderCapture !== 'function') {
72
+ throw new Error('@three-blocks/devtools attached shader capture runtime is incompatible.');
73
+ }
74
+ runtime.configureThreeBlocksShaderCapture(${JSON.stringify(i).replaceAll("<","\\u003c")});
75
+ })();`;await n.addInitScript({content:`${d}
76
+ ${u}`}),await n.addInitScript({content:se(o,i)}),await n.route("**/*",async f=>{let p=f.request(),h=new URL(p.url()),S=h.pathname;if(p.method()==="GET"&&r!=="precompiled"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.(?:webgpu|webgl)\.json$/u.test(S)){await f.fulfill({status:204});return}if(S===K&&p.method()==="GET"){let w=t.read(h.searchParams.get("scene")??"");await f.fulfill(w===void 0?{status:204}:{status:200,contentType:"application/json",body:JSON.stringify(w)});return}let g=S===Re,c=S===K;if((g||c)&&p.method()==="POST"){let w=p.postDataBuffer()??Buffer.alloc(0);if(w.byteLength>Pe){await f.fulfill({status:413,body:"capture payload too large"});return}try{let m=JSON.parse(w.toString("utf8"));c?t.receive(m):e.receive(m),await f.fulfill({status:204});}catch(m){await f.fulfill({status:400,body:m instanceof Error?m.message:String(m)});}return}await f.continue();});}a(re,"configureAttachedContext");var Xe=Object.freeze({".avif":"image/avif",".css":"text/css; charset=utf-8",".gif":"image/gif",".html":"text/html; charset=utf-8",".ico":"image/x-icon",".jpeg":"image/jpeg",".jpg":"image/jpeg",".js":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".mp4":"video/mp4",".png":"image/png",".svg":"image/svg+xml",".wasm":"application/wasm",".webm":"video/webm",".webp":"image/webp",".woff":"font/woff",".woff2":"font/woff2"});function Qe(n){let e=[`<script src="${Ee}"></script>`,`<script type="module" src="${ke}"></script>`].join(""),t=/<head(?:\s[^>]*)?>/iu.exec(n);return t===null?`${e}${n}`:`${n.slice(0,t.index+t[0].length)}${e}${n.slice(t.index+t[0].length)}`}a(Qe,"injectStaticShaderCaptureHtml");function Ze(n,e,t){let r=q(n,e,t);return [`import { configureThreeBlocksShaderCapture } from ${JSON.stringify(Te)};`,`configureThreeBlocksShaderCapture( ${JSON.stringify(r).replaceAll("<","\\u003c")} );`].join(`
77
+ `)}a(Ze,"staticCaptureBootstrap");var et=5e3;function j(n){return Math.max(n.maxTimeoutMs??n.timeoutMs,n.timeoutMs)}a(j,"configuredHardCapMs");function q(n,e,t){return {capture:n==="capture",backend:t,driven:true,forceLive:n!=="precompiled",settleFrames:e.settleFrames,settleTimeoutMs:e.settleTimeoutMs??3e4,...n==="capture"?{deadlineAt:Date.now()+Math.max(1e3,j(e)-et)}:{},readiness:e.readiness,transform:B}}a(q,"shaderCaptureConfiguration");async function tt(n,e){let t=await m(n,e,o=>/\.(?:c|m)?js$/u.test(o),16384),r=false,a=false,s;for(let o of t){let i=(await l(n,o,d.texture,"Static application JavaScript")).data.toString("utf8");if(i.includes("nodeBuilderStateProvider")&&(r=true),i.includes("three-blocks.shader-capture.runtime.v1")&&(a=true,s??=o),r&&a)break}if(!r||!a)throw new Error("The static build does not contain the Three.js shader capture transform. Run `shaders capture` without an explicit driver or URL to preview adapter wiring and build automatically, or add the manual adapter from the package README and rebuild.");return {seen:true,applied:true,alreadyPresent:false,captureApplied:true,...s===void 0?{}:{id:s}}}a(tt,"inspectStaticCaptureTransform");async function rt(n,e){let t;try{t=decodeURIComponent(e);}catch{return}if(t.includes("\0"))return;let r=t.replace(/^\/+/u,""),a=A.resolve(n,r.length===0?"index.html":r);if(!h(n,a)||a===n||(await g(a)&&(await lstat(a)).isDirectory()&&(a=A.join(a,"index.html")),!await g(a)&&A.extname(a).length===0&&(a=A.join(n,"index.html")),!await g(a)))return;let s=await l(n,a,d.texture,"Static application asset");return {data:s.data,file:s.path}}a(rt,"staticRequestFile");async function nt(n,e,t,r,a,s){let o=await realpath(n.root),i=await realpath(A.resolve(o,n.serve));if(!h(o,i)||i===o)throw new Error("--serve must name a built application directory inside the project root.");let d=await tt(o,i),u=await S(),f=Ze(e,r,t),p=se(z(n.runtime.three,t),q(e,r,t)),h$1=createServer((g,c)=>{(async()=>{if(_e(g,c,a,s,e!=="precompiled"))return;let w=new URL(g.url??"/","http://three-blocks.invalid");if(g.method!=="GET"&&g.method!=="HEAD"){c.statusCode=405,c.end("GET or HEAD required");return}let m=w.pathname===Te?u:w.pathname===ke?f:w.pathname===Ee?p:void 0;if(m!==void 0){c.statusCode=200,c.setHeader("Content-Type","text/javascript; charset=utf-8"),c.setHeader("Cache-Control","no-store"),c.end(g.method==="HEAD"?void 0:m);return}let y=await rt(i,w.pathname);if(y===void 0){c.statusCode=404,c.end("Not found");return}let v=A.extname(y.file).toLowerCase(),b=v===".html"?Buffer.from(Qe(y.data.toString("utf8"))):y.data;c.statusCode=200,c.setHeader("Content-Type",Xe[v]??"application/octet-stream"),c.setHeader("Content-Length",String(b.byteLength)),c.setHeader("Cache-Control","no-store"),c.end(g.method==="HEAD"?void 0:b);})().catch(w=>{if(c.headersSent)return c.destroy(w instanceof Error?w:void 0);c.statusCode=500,c.end(w instanceof Error?w.message:String(w));});});await new Promise((g,c)=>{h$1.once("error",c),h$1.listen(0,"127.0.0.1",()=>{h$1.off("error",c),g();});});let S$1=h$1.address();if(!S$1||typeof S$1=="string")throw new Error("Static capture server did not expose an ephemeral TCP address.");return {server:h$1,baseUrl:`http://127.0.0.1:${S$1.port}`,transform:d}}a(nt,"startStaticShaderServer");function at(n,e,t){return n===e?true:t&&n!==void 0&&n!=="capture"&&e!=="capture"}a(at,"canReuseShaderBrowserSession");function ve(n){let e=n instanceof Error?n.message:String(n);return e.includes("Execution context was destroyed")&&e.includes("navigation")||/^launch: Timeout \d+ms exceeded\./u.test(e)||e.includes("Shader browser disconnected before observation completed.")}a(ve,"isRetryableShaderObservationNavigation");var $=class{static{a(this,"PlaywrightShaderDriver");}#e;#t=new ae;#n=new oe;#h;#m;#s;#i;#r;#a;#f;#l;#p;#w;#u=0;#c;constructor(e){this.#e=e;}#d(){return this.#h?.status??this.#m??{seen:false,applied:false,alreadyPresent:false}}async#y(e,t){if(this.#r?.isConnected()===true)return;this.#r=void 0;let r=await Ve();this.#c??=await mkdtemp(A.join(tmpdir(),"three-blocks-shader-cache-"));let a=r.launch({headless:t==="webgl"?this.#e.headed!==true:we(this.#e.headed===true),args:[...t==="webgl"?pe():fe(),`--disk-cache-dir=${this.#c}`],timeout:e.timeoutMs}),s;try{this.#r=await Promise.race([a,new Promise((o,i)=>{s=setTimeout(()=>i(new Error(`launch: Timeout ${e.timeoutMs}ms exceeded.`)),e.timeoutMs);})]);}catch(o){throw a.then(i=>M(()=>i.close()),()=>{}),o}finally{s!==void 0&&clearTimeout(s);}this.#u=0;}async#o(e,t,r){let a;try{return await Promise.race([r(),new Promise((s,o)=>{a=setTimeout(()=>o(new Error(`launch: Timeout ${t.timeoutMs}ms exceeded.`)),t.timeoutMs);})])}catch(s){throw this.#r===e&&(this.#r=void 0),await M(()=>e.close()),s}finally{a!==void 0&&clearTimeout(a);}}async#g(e,t,r){let a=this.#s!==void 0||this.#i!==void 0||this.#e.url!==void 0&&this.#a!==void 0,s=this.#p===t&&(this.#i!==void 0?this.#l===e:at(this.#l,e,r.bridge.legacyLab));if(a&&s){this.#l=e,await this.#y(r,t);return}if(a&&await this.close(),this.#l=e,this.#p=t,this.#e.url!==void 0){let o=new URL(this.#e.url);if(!["http:","https:"].includes(o.protocol)||o.username||o.password||o.hash)throw new Error("Attached shader URL must be an HTTP(S) URL without credentials or a fragment.");this.#a=o.href,this.#m={seen:true,applied:true,alreadyPresent:false,captureApplied:true,id:"attached-application"},await this.#y(r,t);return}if(this.#e.serve!==void 0)try{let o=await nt({root:this.#e.root,runtime:this.#e.runtime,serve:this.#e.serve,...this.#e.headed===void 0?{}:{headed:this.#e.headed}},e,t,r,this.#t,this.#n);this.#i=o.server,this.#m=o.transform,this.#a=o.baseUrl,await this.#y(r,t);return}catch(o){throw await this.close(),o}this.#h=X(this.#e.runtime.three,{disableTimestampQueries:x.env.THREE_BLOCKS_SOFTWARE_WEBGPU==="1",...r.bridge.legacyLab?{}:{capture:{capture:e==="capture",driven:true,forceLive:e!=="precompiled",forceWebGL:t==="webgl",settleFrames:r.settleFrames,settleTimeoutMs:r.settleTimeoutMs??3e4,readiness:r.readiness}}}),this.#f={THREE_BLOCKS_SHADER_TOOL:x.env.THREE_BLOCKS_SHADER_TOOL,THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER:x.env.THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER},x.env.THREE_BLOCKS_SHADER_TOOL="1",x.env.THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER="1";try{let o=await We(this.#e.root);this.#s=await o({root:this.#e.root,logLevel:"error",plugins:[this.#h.plugin,qe(this.#t,this.#n,e!=="precompiled",z(this.#e.runtime.three,t),q(e,r,t))],server:{host:"127.0.0.1",port:0}}),await this.#s.listen();let i=this.#s.httpServer?.address();if(!i||typeof i=="string")throw new Error("Vite did not expose an ephemeral TCP address.");this.#a=`http://127.0.0.1:${i.port}`,await this.#y(r,t);}catch(o){throw await this.close(),o}}async capture(e,t,r="webgpu"){let a$2=Date.now();if(await this.#g("capture",r,t),!this.#r||!this.#a)throw new Error("Shader browser driver did not start.");let s=this.#r,o=await this.#o(s,t,()=>s.newContext({viewport:t.viewport}));this.#e.url!==void 0&&await this.#o(s,t,()=>re(o,this.#t,this.#n,"capture",t,r,z(this.#e.runtime.three,r)));let i=await this.#o(s,t,()=>o.newPage()),d=te(i);this.#n.clear(e.key);let u=j(t),f=this.#t.wait(e.key,u),p=false;u>t.timeoutMs?(async()=>{let m=Math.min(5e3,Math.max(1e3,Math.round(t.timeoutMs/8))),y=Date.now(),v="",b="";for(;!p;){if(await new Promise(k=>setTimeout(k,m)),p)return;let T=this.#n.read(e.key),B=T===void 0?"":JSON.stringify(T);if(B!==v){v=B,y=Date.now();continue}if(Date.now()-y<t.timeoutMs)continue;let E=await xe(i,t.readiness.global);if(p)return;if(!E.alive||E.signature!==b){b=E.signature,y=Date.now();continue}this.#t.cancel(e.key,new Error(`Shader capture "${e.key}" timed out after ${t.timeoutMs}ms without progress (hard cap ${u}ms).`));return}})().catch(()=>{}):void 0;let S=Promise.race([f,d.first.then(m=>Promise.reject(m))]),g=a(()=>{},"resolveDisconnected"),c=new Promise(m=>{g=m;}),w=a(()=>g(new Error("Shader capture browser disconnected before posting a manifest.")),"onDisconnected");s.on("disconnected",w);try{let m=i.goto(ge(this.#a,e,{threeBlocksShaderCapture:"1",capture:"1",captureId:e.key,captureFrames:String(Math.max(4,t.settleFrames)),settleFrames:String(t.settleFrames),...r==="webgl"?{webgl:"1"}:{}}),{waitUntil:"domcontentloaded",timeout:t.timeoutMs}),y=await Je(m,Promise.race([S,c.then(b=>Promise.reject(b))]));Y(this.#d());let v=[...d.page,...d.console];if(v.length>0)throw new Error(`Capture browser errors:
78
+ - ${v.join(`
79
+ - `)}`);return a$1(y)?{...y,timing:{...a$1(y.timing)?y.timing:{},launch:a$2,...this.#n.firstRequest(e.key)===void 0?{}:{firstRequest:this.#n.firstRequest(e.key)},posted:Date.now()}}:y}catch(m){let y=m instanceof Error?m:new Error(String(m));this.#t.cancel(e.key,y),await f.catch(()=>{});let v=this.#n.read(e.key);if(y.message.includes("timed out")){let b=await J(()=>i.evaluate(E=>{let k=globalThis,N=k.__threeBlocksShaderTools,Me=N&&typeof N=="object"?N:void 0,Oe=k.document,O=Reflect.get(k,Symbol.for("three-blocks.shader-capture.cache-value.v1")),I=k.location,Ae=I!==null&&typeof I=="object"&&typeof Reflect.get(I,"href")=="string"?String(Reflect.get(I,"href")):"http://three-blocks.invalid/",je=new URL(Ae).searchParams.get("captureId")??"default",ie=O!==null&&typeof O=="object"&&typeof Reflect.get(O,"registrations")=="function"?Reflect.apply(Reflect.get(O,"registrations"),O,[je]):void 0,de=a(R=>{let _=k;for(let De of R.split(".")){if(_===null||typeof _!="object"&&typeof _!="function")return;_=Reflect.get(_,De);}return _},"resolveGlobal"),le=null,z=null;if(E!==null){let R=de(E);le=R===true||R===false?R:R===void 0?"absent":R!==null&&typeof R.then=="function"?"promise":typeof R;try{let _=JSON.stringify(de(`${E}Diagnostics`));z=typeof _=="string"?_.slice(0,2048):null;}catch{z=null;}}return {documentReadyState:Oe?.readyState??null,parityTargetFrame:Number(k.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(k.__threeBlocksParityCompletedFrame??0),readiness:Me?.readiness??null,readinessGlobal:le,readinessDiagnostics:z,captureCache:O!==null&&typeof O=="object"?{activeScene:Reflect.get(O,"activeScene")??null,registrations:Array.isArray(ie)?ie.slice(0,16).map(R=>R!==null&&typeof R=="object"?{key:Reflect.get(R,"key")??null,kind:Reflect.get(R,"kind")??null}:null):null}:null,threeRuntimeResources:performance.getEntriesByType("resource").map(R=>R.name).filter(R=>R.includes("three.webgpu"))}},t.readiness.global??null)),T=t.readiness.global!==void 0&&b!==null&&b.readinessGlobal!==true,B=b===null?"Capture page did not answer diagnostics before the deadline; its main thread was blocked or gone. ":T?`Application readiness "${t.readiness.global}" never completed (state: ${JSON.stringify(b.readinessGlobal)}${b.readinessDiagnostics===null?"":`, diagnostics: ${b.readinessDiagnostics}`}). `:"";throw new Error(`${B}${y.message} Last capture state for "${e.key}": ${JSON.stringify({page:b,telemetry:v??null,transform:this.#d()})}`)}throw y}finally{p=true,d.dispose(),s.off("disconnected",w),await M(()=>o.close()),this.#u++,(!s.isConnected()||this.#u>=(t.browserRelaunchScenes??8))&&(this.#r===s&&(this.#r=void 0),await M(()=>s.close()),this.#u=0);}}async observe(e,t,r,a,s="webgpu"){for(let o=0;o<2;o++)try{return await this.#S(e,s,t,r,a)}catch(i){if(o===0&&ve(i))continue;throw i}throw new Error(`Shader observation retry was exhausted for scene "${e.key}".`)}async#S(e,t,r,a,s){if(await this.#g(r,t,a),!this.#r||!this.#a)throw new Error("Shader browser driver did not start.");let o=this.#r,i=await this.#o(o,a,()=>o.newContext({viewport:a.viewport}));this.#e.url!==void 0&&await this.#o(o,a,()=>re(i,this.#t,this.#n,r,a,t,z(this.#e.runtime.three,t)));let d=await this.#o(o,a,()=>i.newPage()),u=te(d);this.#n.clear(e.key);try{await d.goto(ge(this.#a,e,{threeBlocksShaderCapture:"1",threeBlocksShaderMode:r,captureId:e.key,...r==="live"?{precompiled:"0"}:{},...t==="webgl"?{webgl:"1"}:{}}),{waitUntil:"domcontentloaded",timeout:a.timeoutMs}),await Promise.race([d.waitForFunction(a.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:j(a)}),u.first.then(c=>Promise.reject(c))]),V(await W(d,a.bridge.legacyLab),e,a.bridge.legacyLab,this.#d(),z(this.#e.runtime.three,t)),await Se(d,a,u),await Promise.race([d.waitForFunction(a.bridge.legacyLab?"true":"globalThis.__threeBlocksShaderTools?.readiness?.firstFrame === true",void 0,{timeout:j(a)}),u.first.then(c=>Promise.reject(c))]),await F(d,a,1);let f=Buffer.from(await d.screenshot({type:"png",timeout:a.timeoutMs})),p=e.parityFrames??a.parity.frames,h=await F(d,a,p,s),S=Buffer.from(await d.screenshot({type:"png",timeout:a.timeoutMs}));e.parityFrames!==void 0&&p<a.parity.frames&&await F(d,a,a.parity.frames-p);let g=V(await W(d,a.bridge.legacyLab),e,a.bridge.legacyLab,this.#d(),z(this.#e.runtime.three,t));return this.#w===void 0&&(this.#w=await d.evaluate(async c=>{if(c==="webgl"){let E=Reflect.get(globalThis,"document").querySelector("canvas")?.getContext("webgl2"),k=E?.getExtension("WEBGL_debug_renderer_info");return {adapter:E&&k?String(E.getParameter(k.UNMASKED_RENDERER_WEBGL)):"WebGL adapter",platform:navigator.platform||navigator.userAgent}}let w=Reflect.get(navigator,"gpu"),m=typeof w=="object"&&w!==null?Reflect.get(w,"requestAdapter"):void 0,y=typeof m=="function"?await Reflect.apply(m,w,[]):void 0,v=typeof y=="object"&&y!==null?Reflect.get(y,"info"):void 0,b=["description","device","architecture","vendor"].flatMap(T=>{let B=typeof v=="object"&&v!==null?Reflect.get(v,T):void 0;return typeof B=="string"&&B.length>0?[B]:[]});return {adapter:[...new Set(b)].join(" \xB7 ")||"WebGPU adapter",platform:navigator.platform||navigator.userAgent}},t)),{scene:e.key,mode:r,...g,frame:h,firstFrameScreenshot:f,screenshot:S,errors:[...u.page,...u.console]}}catch(f){let p=f instanceof Error?f:new Error(String(f));if(/(?:timed?\s*out|timeout)/iu.test(p.message)){let c=this.#n.read(e.key),w=await J(()=>d.evaluate(()=>{let m=globalThis,y=m.__threeBlocksShaderTools,v=y&&typeof y=="object"?y:void 0;return {documentReadyState:m.document?.readyState??null,parityTargetFrame:Number(m.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(m.__threeBlocksParityCompletedFrame??0),readiness:v?.readiness??null,threeRuntimeResources:performance.getEntriesByType("resource").map(T=>T.name).filter(T=>T.includes("three.webgpu"))}}));throw new Error(`${p.message} Last ${r} state for "${e.key}": ${JSON.stringify({page:w,telemetry:c??null})}`)}let h=this.#n.read(e.key),g=(a$1(h)&&Array.isArray(h.demands)&&h.demands.length>0?JSON.stringify(h.demands).slice(0,6e3):void 0)??await J(()=>d.evaluate(c=>{let w=globalThis,m=Reflect.get(w,Symbol.for(c)),y=m!==null&&typeof m=="object"?Reflect.get(m,"readThreeBlocksShaderDemands"):void 0,v=typeof y=="function"?Reflect.apply(y,m,[]):void 0,b=w.__threeBlocksShaderTools,T=Array.isArray(v)&&v.length>0?v:b&&typeof b=="object"?Reflect.get(b,"demands"):void 0;return Array.isArray(T)&&T.length>0?JSON.stringify(T).slice(0,6e3):null},ee));throw typeof g=="string"?new Error(`${p.message}
80
+ ${r} demands: ${g}`):p}finally{u.dispose(),await M(()=>i.close());}}async observePublished(e,t,r="webgpu"){for(let a=0;a<2;a++)try{return await this.#b(e,r,t)}catch(s){if(a===0&&ve(s))continue;throw s}throw new Error(`Published shader observation retry was exhausted for scene "${e.key}".`)}async#b(e,t,r){if(await this.#g("precompiled",t,r),!this.#r||!this.#a)throw new Error("Shader browser driver did not start.");let a=this.#r,s=await this.#o(a,r,()=>a.newContext({viewport:r.viewport}));this.#e.url!==void 0&&await this.#o(a,r,()=>re(s,this.#t,this.#n,"precompiled",r,t,z(this.#e.runtime.three,t)));let o=await this.#o(a,r,()=>s.newPage()),i=te(o);this.#n.clear(e.key);try{await o.goto(ze(this.#a,e,t),{waitUntil:"domcontentloaded",timeout:r.timeoutMs}),await Promise.race([o.waitForFunction(r.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:j(r)}),i.first.then(h=>Promise.reject(h))]),await Se(o,r,i),V(await W(o,r.bridge.legacyLab),e,r.bridge.legacyLab,this.#d(),z(this.#e.runtime.three,t)),await F(o,r,2);let d=await be(o),u=await F(o,r,120),f=await be(o),p=V(await W(o,r.bridge.legacyLab),e,r.bridge.legacyLab,this.#d(),z(this.#e.runtime.three,t));return {scene:e.key,mode:"precompiled",...p,frame:u,firstFrameScreenshot:d,beforeScreenshot:d,screenshot:f,errors:[...i.page,...i.console]}}finally{i.dispose(),await M(()=>s.close());}}timingEnvironment(){return this.#w??{adapter:this.#p==="webgl"?"WebGL adapter":"WebGPU adapter",platform:`${x.platform}/${x.arch}`}}async close(){this.#t.rejectAll(new Error("Shader browser driver closed.")),this.#r&&await M(()=>this.#r?.close()??Promise.resolve());let e=this.#s?.httpServer,t=e?Reflect.get(e,"closeAllConnections"):void 0;if(e&&typeof t=="function"&&Reflect.apply(t,e,[]),this.#s&&await M(()=>this.#s?.close()??Promise.resolve()),this.#i){let r=this.#i;r.closeAllConnections(),await M(()=>new Promise(a=>{r.close(()=>a());}));}if(this.#r=void 0,this.#s=void 0,this.#i=void 0,this.#a=void 0,this.#h=void 0,this.#m=void 0,this.#l=void 0,this.#p=void 0,this.#w=void 0,this.#u=0,this.#c!==void 0&&(await rm(this.#c,{recursive:true,force:true}),this.#c=void 0),this.#f){for(let[r,a]of Object.entries(this.#f))a===void 0?delete x.env[r]:x.env[r]=a;this.#f=void 0;}}};function Tt(n){return new $(n)}a(Tt,"createPlaywrightShaderDriver");function kt(n){return new $(n)}a(kt,"createStaticPlaywrightShaderDriver");function Et(n){return new $(n)}a(Et,"createAttachedPlaywrightShaderDriver");export{Le as a,Z as b,fe as c,we as d,Je as e,Ke as f,se as g,at as h,ve as i,Tt as j,kt as k,Et as l};
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ import {a as a$3,b as b$1}from'./chunk-7N6TU4JG.js';import {c,b,d,a as a$4}from'./chunk-QJFPNM6W.js';import {a as a$2}from'./chunk-65VEJRRT.js';import {a as a$1,j as j$1,k,e,d as d$1}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import x from'process';import {createServer}from'http';import {createRequire}from'module';import {mkdtemp,rm,lstat,realpath}from'fs/promises';import O from'path';import {tmpdir}from'os';import {pathToFileURL}from'url';import {THREE_WEBGPU_R185_COMPATIBILITY}from'three-blocks/shaders';import {transformThreeWebgpuProviderHooks,transformThreeWebgpuCaptureInstrumentation}from'three-blocks/vite';var ee="three-blocks.shader-capture.runtime.v1";var $;async function I(){$===void 0&&($=(async()=>{let e=createRequire(O.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),r=O.resolve(O.dirname(e),"../..");return (await j$1(r,e,a$1.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let t=$;try{return await t}catch(e){throw $===t&&($=void 0),e}}a(I,"loadShaderCaptureRuntimeSource");var we="virtual:three-blocks-shader-capture-client",ge="\0three-blocks:shader-capture-client",te="virtual:three-blocks-shader-capture-runtime",Se="\0three-blocks:shader-capture-runtime";async function ve(){let t=await I(),e=t.replace(/\bexport\{[^{}]*\};?\s*$/u,"");if(e===t)throw new Error("Shader capture browser runtime no longer has the expected final ESM export list.");return e}a(ve,"loadShaderCaptureRuntimeScriptSource");function Je(t){let e=t.split("?",1)[0];return e===void 0?false:e.split(O.sep).join("/").endsWith("/build/three.webgpu.js")}a(Je,"isThreeWebGPUModule");function Te(t){let e=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/u.exec(t);return e?.[1]==="0"&&e[2]==="185"}a(Te,"supportedVersion");function qe(t,e,r={}){if(!Te(e))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${e}".`);let n=transformThreeWebgpuProviderHooks(t,{threeVersion:e,...r.threeRevision===void 0?{}:{threeRevision:r.threeRevision},id:"three/build/three.webgpu.js"}),a=n.state==="already-applied",s=n.code;return r.instrumentCapture&&(s=transformThreeWebgpuCaptureInstrumentation(s,{...r.captureRuntimeImport===void 0?{}:{runtimeImport:r.captureRuntimeImport},...r.forceWebGL===true?{forceWebGL:true}:{}}).code),{code:s,alreadyPresent:a,captureApplied:r.instrumentCapture===true}}a(qe,"applyShaderProviderTransform");var ze=/this\.trackTimestamp\s*=\s*\(\s*parameters\.trackTimestamp\s*===\s*true\s*\);/gu,Ye="Object.defineProperty( this, 'trackTimestamp', { get: () => false, set: () => {} } );";function Re(t,e={}){if(!Te(t))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${t}".`);let r={seen:false,applied:false,alreadyPresent:false};return {plugin:{name:"three-blocks:shader-provider-transform",enforce:"pre",config(){return {optimizeDeps:{exclude:["three","three/webgpu","three/tsl"]},resolve:{dedupe:["three"]}}},resolveId(a){return e.capture&&a===we?ge:e.capture&&a===te?Se:null},async load(a){return e.capture?a===Se?I():a===ge?[`export * from '${te}';`,`import { configureThreeBlocksShaderCapture } from '${te}';`,`configureThreeBlocksShaderCapture( ${JSON.stringify({capture:e.capture.capture,backend:e.capture.forceWebGL===true?"webgl":"webgpu",forceLive:e.capture.forceLive,driven:e.capture.driven,settleFrames:e.capture.settleFrames,settleTimeoutMs:e.capture.settleTimeoutMs,visibilityGuard:e.capture.visibilityGuard,captureId:e.capture.captureId,sessionKey:e.capture.sessionKey,token:e.capture.token,readiness:e.capture.readiness??{},transform:b$1})} );`].join(`
3
+ `):null:null},transform(a,s){if(!Je(s))return null;r.seen=true,r.id=s;try{let o=qe(a,t,{instrumentCapture:e.capture!==void 0,forceWebGL:e.capture?.forceWebGL===!0,...e.capture!==void 0?{captureRuntimeImport:we}:{}}),i=e.disableTimestampQueries===!0?o.code.replace(ze,Ye):o.code;if(e.disableTimestampQueries===!0&&i===o.code)throw new Error("Three.js timestamp tracking anchor drifted; refusing software WebGPU capture.");return r.applied=!0,r.alreadyPresent=o.alreadyPresent,r.captureApplied=o.captureApplied,i===a?null:{code:i,map:null}}catch(o){throw r.error=o instanceof Error?o.message:String(o),o}}},status:r}}a(Re,"createShaderProviderTransform");function ne(t){if(t.error)throw new Error(t.error);if(!t.seen||!t.applied)throw new Error(`The version-gated shader provider transform was not applied (${t.seen?"module seen":"three/webgpu not seen"}).`)}a(ne,"assertShaderProviderTransform");var Be="/__three-blocks/shaders/capture",z="/__three-blocks/shaders/telemetry",xe="/__three-blocks/shaders/runtime.js",Me="/__three-blocks/shaders/bootstrap.js",Ae="/__three-blocks/shaders/bridge.js",Oe=a$1.manifest*2,se=/^[a-z0-9][a-z0-9_-]{0,63}$/u,De=64,je=3e4;async function ar(){try{return (await import('playwright')).chromium}catch(t){throw new Error('Shader browser work requires the optional "playwright" package. Install it in the project and run `npx playwright install chromium`.',{cause:t})}}a(ar,"loadChromium");async function or(t){let e;try{e=createRequire(O.join(t,"package.json")).resolve("vite");}catch(n){throw new Error("Shader capture requires Vite in the target project.",{cause:n})}let r=await import(pathToFileURL(e).href);if(typeof r.createServer!="function")throw new Error(`The target project's Vite entry does not export createServer(): ${e}`);return r.createServer}a(or,"loadProjectCreateServer");var ie=class{static{a(this,"CaptureInbox");}#e=new Map;#r=new Map;wait(e,r){let n=this.#r.get(e);if(n!==void 0)return this.#r.delete(e),Promise.resolve(n);if(this.#e.has(e))throw new Error(`A shader capture is already waiting for scene "${e}".`);return new Promise((a,s)=>{let o=setTimeout(()=>{this.#e.delete(e),s(new Error(`Shader capture "${e}" timed out after ${r}ms.`));},r);this.#e.set(e,{resolve:a,reject:s,timer:o});})}receive(e){if(!a$2(e)||typeof e.scene!="string"||!se.test(e.scene))throw new Error("Capture POST has no safe scene key.");if(!this.#r.has(e.scene)&&!this.#e.has(e.scene)&&this.#r.size>=De)throw new Error("Capture POST exceeds the scene inbox limit.");let r=this.#e.get(e.scene);r?(clearTimeout(r.timer),this.#e.delete(e.scene),r.resolve(e)):this.#r.set(e.scene,e);}cancel(e,r){let n=this.#e.get(e);n&&(clearTimeout(n.timer),this.#e.delete(e),n.reject(r));}rejectAll(e){for(let r of this.#e.values())clearTimeout(r.timer),r.reject(e);this.#e.clear(),this.#r.clear();}};async function sr(t,e){let r=await Promise.race([e.then(n=>({kind:"capture",value:n})),t.then(()=>({kind:"navigation"}))]);return r.kind==="capture"?r.value:e}a(sr,"waitForShaderCaptureAcrossNavigation");var de=class{static{a(this,"TelemetryHub");}#e=new Map;#r=new Map;markFirstRequest(e){se.test(e)&&!this.#r.has(e)&&this.#r.set(e,Date.now());}firstRequest(e){return this.#r.get(e)}receive(e){if(!a$2(e)||typeof e.scene!="string"||!se.test(e.scene))throw new Error("Shader telemetry has no bounded scene key.");if(!this.#e.has(e.scene)&&this.#e.size>=De)throw new Error("Shader telemetry exceeds the scene limit.");this.#e.set(e.scene,e);}read(e){return this.#e.get(e)}clear(e){this.#e.delete(e),this.#r.delete(e);}},ir=a(async(t,e,r,n,a)=>{let s=0;for(;t.__threeBlocksParityUsesAnimationLoop!==true&&s<e;)await n(),s+=1;if(t.__threeBlocksParityUsesAnimationLoop===true){let o=Number(t.__threeBlocksParityCompletedFrame||0),i=Number(r),l=Number.isSafeInteger(i)&&i>=o?i:o+e;for(t.__threeBlocksParityTargetFrame=l;Number(t.__threeBlocksParityCompletedFrame||0)<l;)await n();}return await a(),Number(t.__threeBlocksParityCompletedFrame||0)},"settleShaderParityFrames");function le(t,e){return `(() => {
4
+ const root = globalThis;
5
+ const scene = new URL(location.href).searchParams.get('captureId')
6
+ || 'default';
7
+ const workerCapture = ${JSON.stringify(e??null).replaceAll("<","\\u003c")};
8
+ if (workerCapture) root[Symbol.for('three-blocks.shader-capture.worker-activation.v1')] = { ...workerCapture, scene };
9
+ const randomSeed = (value) => {
10
+ let state = 2166136261;
11
+ for (let index = 0; index < value.length; index++) state = Math.imul(state ^ value.charCodeAt(index), 16777619) >>> 0;
12
+ return state === 0 ? 0x9e3779b9 : state;
13
+ };
14
+ const advanceRandom = (state) => {
15
+ state ^= state << 13;
16
+ state ^= state >>> 17;
17
+ state ^= state << 5;
18
+ return state >>> 0;
19
+ };
20
+ const parityMode = new URL(location.href).searchParams.get('threeBlocksShaderMode');
21
+ if (parityMode === 'live' || parityMode === 'precompiled') {
22
+ root.__threeBlocksParityEpoch = 1700000000000;
23
+ root.__threeBlocksParityTime = 0;
24
+ Date.now = () => root.__threeBlocksParityEpoch + Number(root.__threeBlocksParityTime || 0);
25
+ }
26
+ const randomStreams = new Map();
27
+ Math.random = () => {
28
+ const stackLine = String(new Error().stack || '').split('\\n')[2] || 'unknown';
29
+ const originIndex = stackLine.indexOf(location.origin);
30
+ const callsite = (originIndex >= 0 ? stackLine.slice(0, originIndex) : stackLine).trim() || 'anonymous';
31
+ const next = advanceRandom(randomStreams.get(callsite) ?? randomSeed(scene + '|' + callsite));
32
+ randomStreams.set(callsite, next);
33
+ return next / 4294967296;
34
+ };
35
+ const readiness = { workerReady: false, assetsReady: false, textReady: false, compileEnd: false, firstFrame: false };
36
+ const stats = { buildCalls: 0, renderBuilds: 0, computeBuilds: 0, registeredBuilds: 0, registeredRenderBuilds: 0, registeredComputeBuilds: 0, buildMs: 0, syncBuildMs: 0, asyncBuildElapsedMs: 0, precompiledSetupMs: 0, maxSyncBuildMs: 0, maxPrecompiledSetupMs: 0, hydrationMs: 0, maxHydrationMs: 0, injected: 0, injectedRender: 0, injectedCompute: 0, missed: 0, missedRender: 0, missedCompute: 0, missedKeys: [] };
37
+ const settleParityFrames = ${ir.toString()};
38
+ const settle = (frames, requestedTarget) => settleParityFrames(
39
+ root,
40
+ frames,
41
+ requestedTarget,
42
+ () => new Promise((resolve) => requestAnimationFrame(resolve)),
43
+ () => new Promise((resolve) => setTimeout(resolve, 100)),
44
+ );
45
+ const bridge = { protocolVersion: 1, compatibility: ${JSON.stringify(t)}, transform: ${b$1}, readiness, stats, settle };
46
+ root.__threeBlocksShaderTools = bridge;
47
+ requestAnimationFrame(() => requestAnimationFrame(() => { readiness.firstFrame = true; }));
48
+ const poll = async () => {
49
+ try {
50
+ const response = await fetch('/__three-blocks/shaders/telemetry?scene=' + encodeURIComponent(scene), { cache: 'no-store' });
51
+ if (response.status !== 204 && response.ok) {
52
+ const payload = await response.json();
53
+ if (payload.protocolVersion !== 1 || payload.compatibility !== bridge.compatibility || payload.transform !== bridge.transform) throw new Error('incompatible shader telemetry');
54
+ Object.assign(stats, payload.stats);
55
+ if (Array.isArray(payload.demands)) bridge.demands = payload.demands;
56
+ if (typeof payload.demandTotal === 'number') bridge.demandTotal = payload.demandTotal;
57
+ readiness.workerReady = true;
58
+ if (payload.settled === true) {
59
+ readiness.assetsReady = true;
60
+ readiness.textReady = true;
61
+ readiness.compileEnd = true;
62
+ }
63
+ const smoke = root.__threeBlocksSmoke && typeof root.__threeBlocksSmoke === 'object' ? root.__threeBlocksSmoke : { protocolVersion: 1, worker: { offscreenCanvas: true, visible: true }, readiness: {} };
64
+ smoke.readiness = { ...(smoke.readiness || {}), ...readiness };
65
+ root.__threeBlocksSmoke = smoke;
66
+ }
67
+ } catch {}
68
+ setTimeout(poll, 40);
69
+ };
70
+ void poll();
71
+ })();`}a(le,"publicBridgeScript");function Le(t,e,r,n,a=false){let s=new URL(t.url??"/","http://three-blocks.invalid"),o=s.pathname;if(a&&t.method==="GET"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.(?:webgpu|webgl)\.json$/u.test(o))return e.statusCode=204,e.end(),true;if(o===z&&t.method==="GET"){let h=s.searchParams.get("scene")??"",S=n.read(h);return S===void 0?(e.statusCode=204,e.end()):(e.statusCode=200,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify(S))),true}let i=o===Be,l=o===z;if(!i&&!l)return false;if(t.method!=="POST")return e.statusCode=405,e.end("POST required"),true;let u=[],p=0,f=false;return t.on("data",h=>{p+=h.byteLength,p>Oe?f=true:u.push(h);}),t.on("end",()=>{if(f){e.statusCode=413,e.end("capture payload too large");return}try{let h=JSON.parse(Buffer.concat(u).toString("utf8"));l?n.receive(h):r.receive(h),e.statusCode=204,e.end();}catch(h){e.statusCode=400,e.end(h instanceof Error?h.message:String(h));}}),true}a(Le,"handleCaptureEndpoint");function dr(t,e,r,n,a){return {name:"three-blocks:shader-capture-endpoint",transformIndexHtml(){return [{tag:"script",children:le(n,a),injectTo:"head-prepend"}]},configureServer(s){s.middlewares.use((o,i,l)=>{let p=new URL(o.url??"/","http://three-blocks.invalid").searchParams.get("captureId");p!==null&&e.markFirstRequest(p),!Le(o,i,t,e,r)&&l();});}}}a(dr,"captureEndpointPlugin");function Ee(t,e,r){let n=new URL(e.url,t);for(let[a,s]of Object.entries(r))n.searchParams.set(a,s);return n.href}a(Ee,"browserUrl");function lr(t,e,r){let n=new URL(e.url,t);for(let a of ["capture","precompiled"])n.searchParams.delete(a);return n.searchParams.set("captureId",e.key),n.searchParams.set("threeBlocksShaderCapture","1"),n.searchParams.set("threeBlocksShaderMode","precompiled"),r==="webgl"&&n.searchParams.set("webgl","1"),n.searchParams.set("tbStats","1"),n.href}a(lr,"publishedBrowserUrl");async function M(t){let e;try{await Promise.race([t(),new Promise(r=>{e=setTimeout(r,je);})]);}catch{}finally{e&&clearTimeout(e);}}a(M,"closeBrowserResource");async function q(t){let e;try{return await Promise.race([t().catch(()=>null),new Promise(r=>{e=setTimeout(()=>r(null),je);})])}finally{e!==void 0&&clearTimeout(e);}}a(q,"readPageDiagnostic");function ae(t){let e=a(()=>{},"resolveFirst"),r=new Promise(u=>{e=u;}),n=a(()=>{},"removeBrowserListener"),a$1={console:[],page:[],first:r,dispose:a(()=>n(),"dispose")},s=false,o=a(u=>{s||(s=true,e(new Error(u)));},"report"),i=t.context().browser(),l=a(()=>o("Shader browser disconnected before observation completed."),"onDisconnected");return i?.on("disconnected",l),n=a(()=>{i?.off("disconnected",l);},"removeBrowserListener"),t.on("console",u=>{let p=u.type()==="warning"&&/\[three-blocks\/shaders\].*(?:has no entry|manifest miss|hydration)/iu.test(u.text());if(u.type()!=="error"&&!p||a$4(u.text()))return;let f=u.location().url,h=f.length>0?`${u.text()} (${f})`:u.text();a$1.console.push(h),o(`Browser console ${p?"warning":"error"}: ${h}`);}),t.on("pageerror",u=>{if(a$4(u.message))return;let p=u.stack||u.message;a$1.page.push(p),o(`Browser page error: ${p}`);}),t.on("crash",()=>o("Browser page crashed before shader capture completed.")),t.on("close",()=>o("Browser page closed before shader capture completed.")),a$1}a(ae,"collectErrors");function N(t,e,r=false){return typeof t[e]=="boolean"?t[e]:r}a(N,"booleanField");function ur(t){if(!a$2(t))throw new Error("Browser shader stats are unavailable.");let e=a((r,n=true)=>{let a=t[r];if(typeof a!="number"||!Number.isFinite(a)||a<0||n&&!Number.isSafeInteger(a))throw new Error(`Browser shader stats.${r} is invalid.`);return a},"read");return {buildCalls:e("buildCalls"),renderBuilds:e("renderBuilds"),computeBuilds:e("computeBuilds"),registeredBuilds:e("registeredBuilds"),registeredRenderBuilds:e("registeredRenderBuilds"),registeredComputeBuilds:e("registeredComputeBuilds"),buildMs:e("buildMs",false),syncBuildMs:e("syncBuildMs",false),asyncBuildElapsedMs:e("asyncBuildElapsedMs",false),precompiledSetupMs:e("precompiledSetupMs",false),maxSyncBuildMs:e("maxSyncBuildMs",false),maxPrecompiledSetupMs:e("maxPrecompiledSetupMs",false),hydrationMs:e("hydrationMs",false),maxHydrationMs:e("maxHydrationMs",false),injected:e("injected"),injectedRender:e("injectedRender"),injectedCompute:e("injectedCompute"),missed:e("missed"),missedRender:e("missedRender"),missedCompute:e("missedCompute"),...Array.isArray(t.missedKeys)&&t.missedKeys.every(r=>typeof r=="string")?{missedKeys:t.missedKeys}:{}}}a(ur,"parseStats");function K(t,e,r,n,a){if(!a$2(t))throw new Error("The page did not expose the public shader devtools bridge.");if(!r&&t.protocolVersion!==1)throw new Error(`Scene "${e.key}" exposed an unsupported shader bridge protocol.`);let s=t.readiness;if(!a$2(s))throw new Error("The shader bridge readiness snapshot is invalid.");let o={workerReady:N(s,"workerReady"),assetsReady:N(s,"assetsReady"),textReady:e.requiresText?N(s,"textReady"):true,compileEnd:N(s,"compileEnd"),firstFrame:N(s,"firstFrame",r)};if(!o.workerReady||!o.assetsReady||!o.textReady||!o.compileEnd)throw new Error(`Scene "${e.key}" did not reach worker/assets/text/compile readiness.`);let i=r?a:t.compatibility,l=r?b$1:t.transform;if(i!==a||l!==b$1)throw new Error(`Scene "${e.key}" exposed incompatible shader bridge metadata.`);ne(n);let u=Array.isArray(t.demands)?t.demands.filter(a$2).slice(0,64):void 0;return {compatibility:a,transform:l,readiness:o,stats:ur(t.stats),...u===void 0?{}:{demands:u}}}a(K,"parseBridge");async function J(t,e){return t.evaluate(r=>{let n=globalThis;if(!r)return n.__threeBlocksShaderTools??null;let a=n.__threeBlocks,s=n.__threeBlocksTslStats;if(!a||typeof a!="object")return null;let o=a;return {readiness:{workerReady:o.workerReady===true,assetsReady:o.loadEnd===true||o.assetsReady===true,textReady:o.textReady===true,compileEnd:o.compileEnd===true,firstFrame:true},stats:s}},e)}a(J,"readBridge");async function Ie(t,e){let r=await q(()=>t.evaluate(n=>{let a$1=globalThis,s=a(i=>{let l=a$1;for(let u of i.split(".")){if(l===null||typeof l!="object"&&typeof l!="function")return;l=Reflect.get(l,u);}return l},"resolveGlobal"),o=null;if(n!==null)try{o=JSON.stringify(s(`${n}Diagnostics`))??null;}catch{o=null;}return JSON.stringify({parityCompletedFrame:Number(a$1.__threeBlocksParityCompletedFrame??0),diagnostics:o})},e??null));return r===null?{alive:false,signature:""}:{alive:true,signature:r}}a(Ie,"probePageProgress");async function U(t,e,r,n){let a$1=t.evaluate(async u=>{let f=globalThis.__threeBlocksShaderTools;if(f&&typeof f=="object"){let g=Reflect.get(f,"settle");if(typeof g=="function"){let c=await g(u.frames,u.targetFrame);return typeof c=="number"&&Number.isSafeInteger(c)?c:0}}if(!u.legacy||!u.modulePath)throw new Error("The public shader bridge does not provide deterministic settle().");let h=await import(u.modulePath);if(!h.store||typeof h.store!="object")throw new Error("Legacy deterministic store is unavailable.");let S=h.store;return S.recordFrameCount=0,S.recordFrameRate=60,S.recordTotalFrames=u.frames,S.recording=true,await new Promise((g,c)=>{let y=Date.now(),m=a(()=>{if(S.recording===false)return g();if(Date.now()-y>u.timeoutMs)return c(new Error("Legacy deterministic settle timed out."));setTimeout(m,25);},"poll");m();}),0},{frames:r,targetFrame:n,legacy:e.bridge.legacyLab,modulePath:e.bridge.deterministicModule??null,timeoutMs:e.timeoutMs}),s=j(e),o=false,i,l=(async()=>{let u=Date.now(),p=u,f="";for(;;){let h=s-(Date.now()-u);if(h<=0)throw new Error(`Shader parity settle timed out after ${s}ms.`);let S=e.timeoutMs-(Date.now()-p);if(S<=0){let g=await Ie(t,e.readiness.global);if(o)throw new Error("Shader parity settle already resolved.");if(g.alive&&g.signature===f)throw new Error(`Shader parity settle timed out after ${e.timeoutMs}ms without progress (hard cap ${s}ms).`);f=g.signature,p=Date.now();continue}if(await new Promise(g=>{i=setTimeout(g,Math.min(S,h,2500));}),o)throw new Error("Shader parity settle already resolved.")}})();try{return await Promise.race([a$1,l])}finally{o=true,i!==void 0&&clearTimeout(i),l.catch(()=>{});}}a(U,"settlePage");async function ke(t,e,r){e.readiness.selector===void 0&&e.readiness.global===void 0||await Promise.race([t.waitForFunction(n=>{let a=globalThis;if(n.selector!==void 0&&a.document?.querySelector(n.selector)==null)return false;if(n.global===void 0)return true;let s=a;for(let l of n.global.split(".")){if((typeof s!="object"||s===null)&&typeof s!="function")return false;s=Reflect.get(s,l);}if(s===true)return true;if(typeof s!="object"||s===null||typeof Reflect.get(s,"then")!="function")return false;let o=a.__threeBlocksReadinessState,i=o instanceof Map?o:new Map;return o instanceof Map||(a.__threeBlocksReadinessState=i),i.has(s)||(i.set(s,false),Promise.resolve(s).then(()=>i.set(s,true),()=>i.set(s,false))),i.get(s)===true},e.readiness,{timeout:j(e)}),r.first.then(n=>Promise.reject(n))]);}a(ke,"waitForConfiguredReadiness");async function Ce(t){let e=t.locator("canvas"),n=(await e.evaluateAll(a=>a.map((s,o)=>{let i=s.getBoundingClientRect();return {index:o,area:Math.max(0,i.width)*Math.max(0,i.height)}}))).sort((a,s)=>s.area-a.area)[0];if(n===void 0||n.area<=0)throw new Error("Published page has no visible renderer canvas.");return Buffer.from(await e.nth(n.index).screenshot({type:"png"}))}a(Ce,"primaryCanvasScreenshot");async function oe(t,e,r,n,a,s,o){let i=Y(n,a,s),l=await ve(),u=`(() => {
72
+ const runtime = globalThis[Symbol.for(${JSON.stringify(ee)})];
73
+ if (!runtime || typeof runtime.configureThreeBlocksShaderCapture !== 'function') {
74
+ throw new Error('@three-blocks/devtools attached shader capture runtime is incompatible.');
75
+ }
76
+ runtime.configureThreeBlocksShaderCapture(${JSON.stringify(i).replaceAll("<","\\u003c")});
77
+ })();`;await t.addInitScript({content:`${l}
78
+ ${u}`}),await t.addInitScript({content:le(o,i)}),await t.route("**/*",async p=>{let f=p.request(),h=new URL(f.url()),S=h.pathname;if(f.method()==="GET"&&n!=="precompiled"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.(?:webgpu|webgl)\.json$/u.test(S)){await p.fulfill({status:204});return}if(S===z&&f.method()==="GET"){let y=r.read(h.searchParams.get("scene")??"");await p.fulfill(y===void 0?{status:204}:{status:200,contentType:"application/json",body:JSON.stringify(y)});return}let g=S===Be,c=S===z;if((g||c)&&f.method()==="POST"){let y=f.postDataBuffer()??Buffer.alloc(0);if(y.byteLength>Oe){await p.fulfill({status:413,body:"capture payload too large"});return}try{let m=JSON.parse(y.toString("utf8"));c?r.receive(m):e.receive(m),await p.fulfill({status:204});}catch(m){await p.fulfill({status:400,body:m instanceof Error?m.message:String(m)});}return}await p.continue();});}a(oe,"configureAttachedContext");var cr=Object.freeze({".avif":"image/avif",".css":"text/css; charset=utf-8",".gif":"image/gif",".html":"text/html; charset=utf-8",".ico":"image/x-icon",".jpeg":"image/jpeg",".jpg":"image/jpeg",".js":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".mp4":"video/mp4",".png":"image/png",".svg":"image/svg+xml",".wasm":"application/wasm",".webm":"video/webm",".webp":"image/webp",".woff":"font/woff",".woff2":"font/woff2"});function hr(t){let e=[`<script src="${Ae}"></script>`,`<script type="module" src="${Me}"></script>`].join(""),r=/<head(?:\s[^>]*)?>/iu.exec(t);return r===null?`${e}${t}`:`${t.slice(0,r.index+r[0].length)}${e}${t.slice(r.index+r[0].length)}`}a(hr,"injectStaticShaderCaptureHtml");function mr(t,e,r){let n=Y(t,e,r);return [`import { configureThreeBlocksShaderCapture } from ${JSON.stringify(xe)};`,`configureThreeBlocksShaderCapture( ${JSON.stringify(n).replaceAll("<","\\u003c")} );`].join(`
79
+ `)}a(mr,"staticCaptureBootstrap");var pr=5e3;function j(t){return Math.max(t.maxTimeoutMs??t.timeoutMs,t.timeoutMs)}a(j,"configuredHardCapMs");function Y(t,e,r){return {capture:t==="capture",backend:r,driven:true,forceLive:t!=="precompiled",settleFrames:e.settleFrames,settleTimeoutMs:e.settleTimeoutMs??3e4,...t==="capture"?{deadlineAt:Date.now()+Math.max(1e3,j(e)-pr)}:{},readiness:e.readiness,transform:b$1}}a(Y,"shaderCaptureConfiguration");async function fr(t,e){let r=await k(t,e,o=>/\.(?:c|m)?js$/u.test(o),16384),n=false,a=false,s;for(let o of r){let i=(await j$1(t,o,a$1.texture,"Static application JavaScript")).data.toString("utf8");if(i.includes("nodeBuilderStateProvider")&&(n=true),i.includes("three-blocks.shader-capture.runtime.v1")&&(a=true,s??=o),n&&a)break}if(!n||!a)throw new Error("The static build does not contain the Three.js shader capture transform. Run `shaders capture` without an explicit driver or URL to preview adapter wiring and build automatically, or add the manual adapter from the package README and rebuild.");return {seen:true,applied:true,alreadyPresent:false,captureApplied:true,...s===void 0?{}:{id:s}}}a(fr,"inspectStaticCaptureTransform");async function yr(t,e$1){let r;try{r=decodeURIComponent(e$1);}catch{return}if(r.includes("\0"))return;let n=r.replace(/^\/+/u,""),a=O.resolve(t,n.length===0?"index.html":n);if(!e(t,a)||a===t||(await d$1(a)&&(await lstat(a)).isDirectory()&&(a=O.join(a,"index.html")),!await d$1(a)&&O.extname(a).length===0&&(a=O.join(t,"index.html")),!await d$1(a)))return;let s=await j$1(t,a,a$1.texture,"Static application asset");return {data:s.data,file:s.path}}a(yr,"staticRequestFile");async function wr(t,e$1,r,n,a,s){let o=await realpath(t.root),i=await realpath(O.resolve(o,t.serve));if(!e(o,i)||i===o)throw new Error("--serve must name a built application directory inside the project root.");let l=await fr(o,i),u=await I(),p=mr(e$1,n,r),f=le(a$3(t.runtime.three,r),Y(e$1,n,r)),h=createServer((g,c)=>{(async()=>{if(Le(g,c,a,s,e$1!=="precompiled"))return;let y=new URL(g.url??"/","http://three-blocks.invalid");if(g.method!=="GET"&&g.method!=="HEAD"){c.statusCode=405,c.end("GET or HEAD required");return}let m=y.pathname===xe?u:y.pathname===Me?p:y.pathname===Ae?f:void 0;if(m!==void 0){c.statusCode=200,c.setHeader("Content-Type","text/javascript; charset=utf-8"),c.setHeader("Cache-Control","no-store"),c.end(g.method==="HEAD"?void 0:m);return}let w=await yr(i,y.pathname);if(w===void 0){c.statusCode=404,c.end("Not found");return}let v=O.extname(w.file).toLowerCase(),b=v===".html"?Buffer.from(hr(w.data.toString("utf8"))):w.data;c.statusCode=200,c.setHeader("Content-Type",cr[v]??"application/octet-stream"),c.setHeader("Content-Length",String(b.byteLength)),c.setHeader("Cache-Control","no-store"),c.end(g.method==="HEAD"?void 0:b);})().catch(y=>{if(c.headersSent)return c.destroy(y instanceof Error?y:void 0);c.statusCode=500,c.end(y instanceof Error?y.message:String(y));});});await new Promise((g,c)=>{h.once("error",c),h.listen(0,"127.0.0.1",()=>{h.off("error",c),g();});});let S=h.address();if(!S||typeof S=="string")throw new Error("Static capture server did not expose an ephemeral TCP address.");return {server:h,baseUrl:`http://127.0.0.1:${S.port}`,transform:l}}a(wr,"startStaticShaderServer");function gr(t,e,r){return t===e?true:r&&t!==void 0&&t!=="capture"&&e!=="capture"}a(gr,"canReuseShaderBrowserSession");function _e(t){let e=t instanceof Error?t.message:String(t);return e.includes("Execution context was destroyed")&&e.includes("navigation")||/^launch: Timeout \d+ms exceeded\./u.test(e)||e.includes("Shader browser disconnected before observation completed.")}a(_e,"isRetryableShaderObservationNavigation");var H=class{static{a(this,"PlaywrightShaderDriver");}#e;#r=new ie;#n=new de;#h;#m;#s;#i;#t;#a;#p;#l;#f;#y;#u=0;#c;constructor(e){this.#e=e;}#d(){return this.#h?.status??this.#m??{seen:false,applied:false,alreadyPresent:false}}async#w(e,r){if(this.#t?.isConnected()===true)return;this.#t=void 0;let n=await ar();this.#c??=await mkdtemp(O.join(tmpdir(),"three-blocks-shader-cache-"));let a=n.launch({headless:r==="webgl"?this.#e.headed!==true:d(this.#e.headed===true),args:[...r==="webgl"?c():b(),`--disk-cache-dir=${this.#c}`],timeout:e.timeoutMs}),s;try{this.#t=await Promise.race([a,new Promise((o,i)=>{s=setTimeout(()=>i(new Error(`launch: Timeout ${e.timeoutMs}ms exceeded.`)),e.timeoutMs);})]);}catch(o){throw a.then(i=>M(()=>i.close()),()=>{}),o}finally{s!==void 0&&clearTimeout(s);}this.#u=0;}async#o(e,r,n){let a;try{return await Promise.race([n(),new Promise((s,o)=>{a=setTimeout(()=>o(new Error(`launch: Timeout ${r.timeoutMs}ms exceeded.`)),r.timeoutMs);})])}catch(s){throw this.#t===e&&(this.#t=void 0),await M(()=>e.close()),s}finally{a!==void 0&&clearTimeout(a);}}async#g(e,r,n){let a=this.#s!==void 0||this.#i!==void 0||this.#e.url!==void 0&&this.#a!==void 0,s=this.#f===r&&(this.#i!==void 0?this.#l===e:gr(this.#l,e,n.bridge.legacyLab));if(a&&s){this.#l=e,await this.#w(n,r);return}if(a&&await this.close(),this.#l=e,this.#f=r,this.#e.url!==void 0){let o=new URL(this.#e.url);if(!["http:","https:"].includes(o.protocol)||o.username||o.password||o.hash)throw new Error("Attached shader URL must be an HTTP(S) URL without credentials or a fragment.");this.#a=o.href,this.#m={seen:true,applied:true,alreadyPresent:false,captureApplied:true,id:"attached-application"},await this.#w(n,r);return}if(this.#e.serve!==void 0)try{let o=await wr({root:this.#e.root,runtime:this.#e.runtime,serve:this.#e.serve,...this.#e.headed===void 0?{}:{headed:this.#e.headed}},e,r,n,this.#r,this.#n);this.#i=o.server,this.#m=o.transform,this.#a=o.baseUrl,await this.#w(n,r);return}catch(o){throw await this.close(),o}this.#h=Re(this.#e.runtime.three,{disableTimestampQueries:x.env.THREE_BLOCKS_SOFTWARE_WEBGPU==="1",...n.bridge.legacyLab?{}:{capture:{capture:e==="capture",driven:true,forceLive:e!=="precompiled",forceWebGL:r==="webgl",settleFrames:n.settleFrames,settleTimeoutMs:n.settleTimeoutMs??3e4,readiness:n.readiness}}}),this.#p={THREE_BLOCKS_SHADER_TOOL:x.env.THREE_BLOCKS_SHADER_TOOL,THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER:x.env.THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER},x.env.THREE_BLOCKS_SHADER_TOOL="1",x.env.THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER="1";try{let o=await or(this.#e.root);this.#s=await o({root:this.#e.root,logLevel:"error",plugins:[this.#h.plugin,dr(this.#r,this.#n,e!=="precompiled",a$3(this.#e.runtime.three,r),Y(e,n,r))],server:{host:"127.0.0.1",port:0}}),await this.#s.listen();let i=this.#s.httpServer?.address();if(!i||typeof i=="string")throw new Error("Vite did not expose an ephemeral TCP address.");this.#a=`http://127.0.0.1:${i.port}`,await this.#w(n,r);}catch(o){throw await this.close(),o}}async capture(e,r,n="webgpu"){let a$1=Date.now();if(await this.#g("capture",n,r),!this.#t||!this.#a)throw new Error("Shader browser driver did not start.");let s=this.#t,o=await this.#o(s,r,()=>s.newContext({viewport:r.viewport}));this.#e.url!==void 0&&await this.#o(s,r,()=>oe(o,this.#r,this.#n,"capture",r,n,a$3(this.#e.runtime.three,n)));let i=await this.#o(s,r,()=>o.newPage()),l=ae(i);this.#n.clear(e.key);let u=j(r),p=this.#r.wait(e.key,u),f=false;u>r.timeoutMs?(async()=>{let m=Math.min(5e3,Math.max(1e3,Math.round(r.timeoutMs/8))),w=Date.now(),v="",b="";for(;!f;){if(await new Promise(P=>setTimeout(P,m)),f)return;let R=this.#n.read(e.key),_=R===void 0?"":JSON.stringify(R);if(_!==v){v=_,w=Date.now();continue}if(Date.now()-w<r.timeoutMs)continue;let E=await Ie(i,r.readiness.global);if(f)return;if(!E.alive||E.signature!==b){b=E.signature,w=Date.now();continue}this.#r.cancel(e.key,new Error(`Shader capture "${e.key}" timed out after ${r.timeoutMs}ms without progress (hard cap ${u}ms).`));return}})().catch(()=>{}):void 0;let S=Promise.race([p,l.first.then(m=>Promise.reject(m))]),g=a(()=>{},"resolveDisconnected"),c=new Promise(m=>{g=m;}),y=a(()=>g(new Error("Shader capture browser disconnected before posting a manifest.")),"onDisconnected");s.on("disconnected",y);try{let m=i.goto(Ee(this.#a,e,{threeBlocksShaderCapture:"1",capture:"1",captureId:e.key,captureFrames:String(Math.max(4,r.settleFrames)),settleFrames:String(r.settleFrames),...n==="webgl"?{webgl:"1"}:{}}),{waitUntil:"domcontentloaded",timeout:r.timeoutMs}),w=await sr(m,Promise.race([S,c.then(b=>Promise.reject(b))]));ne(this.#d());let v=[...l.page,...l.console];if(v.length>0)throw new Error(`Capture browser errors:
80
+ - ${v.join(`
81
+ - `)}`);return a$2(w)?{...w,timing:{...a$2(w.timing)?w.timing:{},launch:a$1,...this.#n.firstRequest(e.key)===void 0?{}:{firstRequest:this.#n.firstRequest(e.key)},posted:Date.now()}}:w}catch(m){let w=m instanceof Error?m:new Error(String(m));this.#r.cancel(e.key,w),await p.catch(()=>{});let v=this.#n.read(e.key);if(w.message.includes("timed out")){let b=await q(()=>i.evaluate(E=>{let P=globalThis,G=P.__threeBlocksShaderTools,Fe=G&&typeof G=="object"?G:void 0,$e=P.document,A=Reflect.get(P,Symbol.for("three-blocks.shader-capture.cache-value.v1")),W=P.location,Ne=W!==null&&typeof W=="object"&&typeof Reflect.get(W,"href")=="string"?String(Reflect.get(W,"href")):"http://three-blocks.invalid/",Ue=new URL(Ne).searchParams.get("captureId")??"default",ue=A!==null&&typeof A=="object"&&typeof Reflect.get(A,"registrations")=="function"?Reflect.apply(Reflect.get(A,"registrations"),A,[Ue]):void 0,ce=a(T=>{let B=P;for(let He of T.split(".")){if(B===null||typeof B!="object"&&typeof B!="function")return;B=Reflect.get(B,He);}return B},"resolveGlobal"),he=null,Q=null;if(E!==null){let T=ce(E);he=T===true||T===false?T:T===void 0?"absent":T!==null&&typeof T.then=="function"?"promise":typeof T;try{let B=JSON.stringify(ce(`${E}Diagnostics`));Q=typeof B=="string"?B.slice(0,2048):null;}catch{Q=null;}}return {documentReadyState:$e?.readyState??null,parityTargetFrame:Number(P.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(P.__threeBlocksParityCompletedFrame??0),readiness:Fe?.readiness??null,readinessGlobal:he,readinessDiagnostics:Q,captureCache:A!==null&&typeof A=="object"?{activeScene:Reflect.get(A,"activeScene")??null,registrations:Array.isArray(ue)?ue.slice(0,16).map(T=>T!==null&&typeof T=="object"?{key:Reflect.get(T,"key")??null,kind:Reflect.get(T,"kind")??null}:null):null}:null,threeRuntimeResources:performance.getEntriesByType("resource").map(T=>T.name).filter(T=>T.includes("three.webgpu"))}},r.readiness.global??null)),R=r.readiness.global!==void 0&&b!==null&&b.readinessGlobal!==true,_=b===null?"Capture page did not answer diagnostics before the deadline; its main thread was blocked or gone. ":R?`Application readiness "${r.readiness.global}" never completed (state: ${JSON.stringify(b.readinessGlobal)}${b.readinessDiagnostics===null?"":`, diagnostics: ${b.readinessDiagnostics}`}). `:"";throw new Error(`${_}${w.message} Last capture state for "${e.key}": ${JSON.stringify({page:b,telemetry:v??null,transform:this.#d()})}`)}throw w}finally{f=true,l.dispose(),s.off("disconnected",y),await M(()=>o.close()),this.#u++,(!s.isConnected()||this.#u>=(r.browserRelaunchScenes??8))&&(this.#t===s&&(this.#t=void 0),await M(()=>s.close()),this.#u=0);}}async observe(e,r,n,a,s="webgpu"){for(let o=0;o<2;o++)try{return await this.#S(e,s,r,n,a)}catch(i){if(o===0&&_e(i))continue;throw i}throw new Error(`Shader observation retry was exhausted for scene "${e.key}".`)}async#S(e,r,n,a,s){if(await this.#g(n,r,a),!this.#t||!this.#a)throw new Error("Shader browser driver did not start.");let o=this.#t,i=await this.#o(o,a,()=>o.newContext({viewport:a.viewport}));this.#e.url!==void 0&&await this.#o(o,a,()=>oe(i,this.#r,this.#n,n,a,r,a$3(this.#e.runtime.three,r)));let l=await this.#o(o,a,()=>i.newPage()),u=ae(l);this.#n.clear(e.key);try{await l.goto(Ee(this.#a,e,{threeBlocksShaderCapture:"1",threeBlocksShaderMode:n,captureId:e.key,...n==="live"?{precompiled:"0"}:{},...r==="webgl"?{webgl:"1"}:{}}),{waitUntil:"domcontentloaded",timeout:a.timeoutMs}),await Promise.race([l.waitForFunction(a.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:j(a)}),u.first.then(c=>Promise.reject(c))]),K(await J(l,a.bridge.legacyLab),e,a.bridge.legacyLab,this.#d(),a$3(this.#e.runtime.three,r)),await ke(l,a,u),await Promise.race([l.waitForFunction(a.bridge.legacyLab?"true":"globalThis.__threeBlocksShaderTools?.readiness?.firstFrame === true",void 0,{timeout:j(a)}),u.first.then(c=>Promise.reject(c))]),await U(l,a,1);let p=Buffer.from(await l.screenshot({type:"png",timeout:a.timeoutMs})),f=e.parityFrames??a.parity.frames,h=await U(l,a,f,s),S=Buffer.from(await l.screenshot({type:"png",timeout:a.timeoutMs}));e.parityFrames!==void 0&&f<a.parity.frames&&await U(l,a,a.parity.frames-f);let g=K(await J(l,a.bridge.legacyLab),e,a.bridge.legacyLab,this.#d(),a$3(this.#e.runtime.three,r));return this.#y===void 0&&(this.#y=await l.evaluate(async c=>{if(c==="webgl"){let E=Reflect.get(globalThis,"document").querySelector("canvas")?.getContext("webgl2"),P=E?.getExtension("WEBGL_debug_renderer_info");return {adapter:E&&P?String(E.getParameter(P.UNMASKED_RENDERER_WEBGL)):"WebGL adapter",platform:navigator.platform||navigator.userAgent}}let y=Reflect.get(navigator,"gpu"),m=typeof y=="object"&&y!==null?Reflect.get(y,"requestAdapter"):void 0,w=typeof m=="function"?await Reflect.apply(m,y,[]):void 0,v=typeof w=="object"&&w!==null?Reflect.get(w,"info"):void 0,b=["description","device","architecture","vendor"].flatMap(R=>{let _=typeof v=="object"&&v!==null?Reflect.get(v,R):void 0;return typeof _=="string"&&_.length>0?[_]:[]});return {adapter:[...new Set(b)].join(" \xB7 ")||"WebGPU adapter",platform:navigator.platform||navigator.userAgent}},r)),{scene:e.key,mode:n,...g,frame:h,firstFrameScreenshot:p,screenshot:S,errors:[...u.page,...u.console]}}catch(p){let f=p instanceof Error?p:new Error(String(p));if(/(?:timed?\s*out|timeout)/iu.test(f.message)){let c=this.#n.read(e.key),y=await q(()=>l.evaluate(()=>{let m=globalThis,w=m.__threeBlocksShaderTools,v=w&&typeof w=="object"?w:void 0;return {documentReadyState:m.document?.readyState??null,parityTargetFrame:Number(m.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(m.__threeBlocksParityCompletedFrame??0),readiness:v?.readiness??null,threeRuntimeResources:performance.getEntriesByType("resource").map(R=>R.name).filter(R=>R.includes("three.webgpu"))}}));throw new Error(`${f.message} Last ${n} state for "${e.key}": ${JSON.stringify({page:y,telemetry:c??null})}`)}let h=this.#n.read(e.key),g=(a$2(h)&&Array.isArray(h.demands)&&h.demands.length>0?JSON.stringify(h.demands).slice(0,6e3):void 0)??await q(()=>l.evaluate(c=>{let y=globalThis,m=Reflect.get(y,Symbol.for(c)),w=m!==null&&typeof m=="object"?Reflect.get(m,"readThreeBlocksShaderDemands"):void 0,v=typeof w=="function"?Reflect.apply(w,m,[]):void 0,b=y.__threeBlocksShaderTools,R=Array.isArray(v)&&v.length>0?v:b&&typeof b=="object"?Reflect.get(b,"demands"):void 0;return Array.isArray(R)&&R.length>0?JSON.stringify(R).slice(0,6e3):null},ee));throw typeof g=="string"?new Error(`${f.message}
82
+ ${n} demands: ${g}`):f}finally{u.dispose(),await M(()=>i.close());}}async observePublished(e,r,n="webgpu"){for(let a=0;a<2;a++)try{return await this.#b(e,n,r)}catch(s){if(a===0&&_e(s))continue;throw s}throw new Error(`Published shader observation retry was exhausted for scene "${e.key}".`)}async#b(e,r,n){if(await this.#g("precompiled",r,n),!this.#t||!this.#a)throw new Error("Shader browser driver did not start.");let a=this.#t,s=await this.#o(a,n,()=>a.newContext({viewport:n.viewport}));this.#e.url!==void 0&&await this.#o(a,n,()=>oe(s,this.#r,this.#n,"precompiled",n,r,a$3(this.#e.runtime.three,r)));let o=await this.#o(a,n,()=>s.newPage()),i=ae(o);this.#n.clear(e.key);try{await o.goto(lr(this.#a,e,r),{waitUntil:"domcontentloaded",timeout:n.timeoutMs}),await Promise.race([o.waitForFunction(n.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:j(n)}),i.first.then(h=>Promise.reject(h))]),await ke(o,n,i),K(await J(o,n.bridge.legacyLab),e,n.bridge.legacyLab,this.#d(),a$3(this.#e.runtime.three,r)),await U(o,n,2);let l=await Ce(o),u=await U(o,n,120),p=await Ce(o),f=K(await J(o,n.bridge.legacyLab),e,n.bridge.legacyLab,this.#d(),a$3(this.#e.runtime.three,r));return {scene:e.key,mode:"precompiled",...f,frame:u,firstFrameScreenshot:l,beforeScreenshot:l,screenshot:p,errors:[...i.page,...i.console]}}finally{i.dispose(),await M(()=>s.close());}}timingEnvironment(){return this.#y??{adapter:this.#f==="webgl"?"WebGL adapter":"WebGPU adapter",platform:`${x.platform}/${x.arch}`}}async close(){this.#r.rejectAll(new Error("Shader browser driver closed.")),this.#t&&await M(()=>this.#t?.close()??Promise.resolve());let e=this.#s?.httpServer,r=e?Reflect.get(e,"closeAllConnections"):void 0;if(e&&typeof r=="function"&&Reflect.apply(r,e,[]),this.#s&&await M(()=>this.#s?.close()??Promise.resolve()),this.#i){let n=this.#i;n.closeAllConnections(),await M(()=>new Promise(a=>{n.close(()=>a());}));}if(this.#t=void 0,this.#s=void 0,this.#i=void 0,this.#a=void 0,this.#h=void 0,this.#m=void 0,this.#l=void 0,this.#f=void 0,this.#y=void 0,this.#u=0,this.#c!==void 0&&(await rm(this.#c,{recursive:true,force:true}),this.#c=void 0),this.#p){for(let[n,a]of Object.entries(this.#p))a===void 0?delete x.env[n]:x.env[n]=a;this.#p=void 0;}}};function Jr(t){return new H(t)}a(Jr,"createPlaywrightShaderDriver");function qr(t){return new H(t)}a(qr,"createStaticPlaywrightShaderDriver");function zr(t){return new H(t)}a(zr,"createAttachedPlaywrightShaderDriver");export{sr as a,ir as b,le as c,gr as d,_e as e,Jr as f,qr as g,zr as h};
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {a as a$2}from'./chunk-ZT6T2W4B.js';import {e as e$1,g}from'./chunk-NPLE7PPF.js';import {a as a$1,c as c$1}from'./chunk-65VEJRRT.js';import {c,d as d$1,f,e,i}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {THREE_WEBGL_R185_COMPATIBILITY,THREE_WEBGPU_R185_COMPATIBILITY,THREE_R186DEV_VERSION,THREE_WEBGPU_R186DEV_COMPATIBILITY,parsePrecompiledManifest,SHADER_HYDRATION_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_ADDRESS_SCHEMA_VERSION,PRECOMPILED_MANIFEST_VERSION}from'three-blocks/shaders';import {lstat,readFile,unlink,mkdir,readdir}from'fs/promises';import d from'path';function v(e,r="webgpu"){if(/^0\.185\./u.test(e))return r==="webgl"?THREE_WEBGL_R185_COMPATIBILITY:THREE_WEBGPU_R185_COMPATIBILITY;if(e===THREE_R186DEV_VERSION&&r==="webgpu")return THREE_WEBGPU_R186DEV_COMPATIBILITY;throw new Error(`Three.js ${e} is outside the supported shader compatibility contracts.`)}a(v,"shaderCompatibilityForThree");var be=62,de="timing.local.json",ce="timing.json",q="parity.json",O=4096,Ee=4096;function W(e,r,n=8192){if(typeof e!="string"||e.length===0||e.length>n||/[\u0000\u007f]/u.test(e))throw new Error(`${r} must be a bounded non-empty string.`);return e}a(W,"boundedString");function p(e,r,n=true){if(typeof e!="number"||!Number.isFinite(e)||e<0||n&&!Number.isSafeInteger(e))throw new Error(`${r} must be a non-negative ${n?"integer":"finite number"}.`);return e}a(p,"nonNegativeNumber");function Re(e){if(!a$1(e))throw new Error("Shader capture stats are missing.");let r={buildCalls:p(e.buildCalls,"capture stats.buildCalls"),renderBuilds:p(e.renderBuilds,"capture stats.renderBuilds"),computeBuilds:p(e.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:p(e.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:p(e.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:p(e.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:p(e.buildMs,"capture stats.buildMs",false),syncBuildMs:p(e.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:p(e.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:p(e.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:p(e.maxSyncBuildMs??e.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:p(e.maxPrecompiledSetupMs??e.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:p(e.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:p(e.maxHydrationMs??e.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:p(e.injected,"capture stats.injected"),injectedRender:p(e.injectedRender,"capture stats.injectedRender"),injectedCompute:p(e.injectedCompute,"capture stats.injectedCompute"),missed:p(e.missed,"capture stats.missed"),missedRender:p(e.missedRender,"capture stats.missedRender"),missedCompute:p(e.missedCompute,"capture stats.missedCompute"),...Array.isArray(e.missedKeys)&&e.missedKeys.every(n=>typeof n=="string")?{missedKeys:e.missedKeys.slice(0,O)}:{}};if(r.renderBuilds+r.computeBuilds!==r.buildCalls||r.registeredRenderBuilds+r.registeredComputeBuilds!==r.registeredBuilds||r.injectedRender+r.injectedCompute!==r.injected||r.missedRender+r.missedCompute!==r.missed||r.registeredBuilds>r.buildCalls||Math.abs(r.syncBuildMs+r.asyncBuildElapsedMs-r.buildMs)>.001||r.maxSyncBuildMs>r.syncBuildMs+.001||r.maxPrecompiledSetupMs>r.precompiledSetupMs+.001||r.maxHydrationMs>r.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return r}a(Re,"captureStats");function Me(e){if(!Array.isArray(e)||e.length>O)throw new Error("Shader capture skipped builds are invalid.");return e.map((r,n)=>{if(!a$1(r)||r.kind!=="render"&&r.kind!=="compute")throw new Error(`Shader capture skipped build ${n} is invalid.`);return {kind:r.kind,name:W(r.name,`skipped build ${n} name`,512),reason:W(r.reason,`skipped build ${n} reason`)}})}a(Me,"skippedBuilds");function ke(e){let r=0,n=0,t=0,i=0;for(let s of Object.values(e.entries)){let o=e.states[s];o!==void 0&&((o.vertex!==null||o.fragment!==null)&&r++,o.vertex!==null&&n++,o.fragment!==null&&t++,o.compute!==null&&i++);}return {render:r,vertex:n,fragment:t,compute:i}}a(ke,"shaderCoverage");function Le(e,r){if(!a$1(e))throw new Error("Shader capture payload must be an object.");if(e.scene!==r.scene)throw new Error(`Shader capture scene does not match "${r.scene}".`);if(e.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let n=r.backend??"webgpu",t=v(r.runtime.three,n);if(e.compatibility!==t)throw new Error(`Shader capture compatibility must be "${t}".`);if(!a$1(e.entries))throw new Error("Shader capture entries must be an object.");if(typeof e.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let i=Object.keys(e.entries).length;if(i>O)throw new Error(`Shader capture must contain at most ${O} entries.`);if(!Array.isArray(e.errors)||e.errors.length>Ee)throw new Error("Shader capture errors are invalid.");let s=e.errors.map((w,a)=>W(w,`capture error ${a}`,64*1024));if(s.length>0)throw new Error(`Shader capture failed:
2
+ import {a as a$2}from'./chunk-ZT6T2W4B.js';import {e as e$1,g}from'./chunk-NPLE7PPF.js';import {a as a$1,c as c$1}from'./chunk-65VEJRRT.js';import {c,d as d$1,f,e,i}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {THREE_WEBGL_R185_COMPATIBILITY,THREE_WEBGPU_R185_COMPATIBILITY,THREE_R186DEV_VERSION,THREE_WEBGPU_R186DEV_COMPATIBILITY,parsePrecompiledManifest,SHADER_HYDRATION_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_ADDRESS_SCHEMA_VERSION,PRECOMPILED_MANIFEST_VERSION}from'three-blocks/shaders';import {lstat,readFile,unlink,mkdir,readdir}from'fs/promises';import d from'path';function v(e,r="webgpu"){if(/^0\.185\./u.test(e))return r==="webgl"?THREE_WEBGL_R185_COMPATIBILITY:THREE_WEBGPU_R185_COMPATIBILITY;if(e===THREE_R186DEV_VERSION&&r==="webgpu")return THREE_WEBGPU_R186DEV_COMPATIBILITY;throw new Error(`Three.js ${e} is outside the supported shader compatibility contracts.`)}a(v,"shaderCompatibilityForThree");var be=63,de="timing.local.json",ce="timing.json",q="parity.json",O=4096,Ee=4096;function W(e,r,n=8192){if(typeof e!="string"||e.length===0||e.length>n||/[\u0000\u007f]/u.test(e))throw new Error(`${r} must be a bounded non-empty string.`);return e}a(W,"boundedString");function p(e,r,n=true){if(typeof e!="number"||!Number.isFinite(e)||e<0||n&&!Number.isSafeInteger(e))throw new Error(`${r} must be a non-negative ${n?"integer":"finite number"}.`);return e}a(p,"nonNegativeNumber");function Re(e){if(!a$1(e))throw new Error("Shader capture stats are missing.");let r={buildCalls:p(e.buildCalls,"capture stats.buildCalls"),renderBuilds:p(e.renderBuilds,"capture stats.renderBuilds"),computeBuilds:p(e.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:p(e.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:p(e.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:p(e.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:p(e.buildMs,"capture stats.buildMs",false),syncBuildMs:p(e.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:p(e.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:p(e.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:p(e.maxSyncBuildMs??e.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:p(e.maxPrecompiledSetupMs??e.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:p(e.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:p(e.maxHydrationMs??e.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:p(e.injected,"capture stats.injected"),injectedRender:p(e.injectedRender,"capture stats.injectedRender"),injectedCompute:p(e.injectedCompute,"capture stats.injectedCompute"),missed:p(e.missed,"capture stats.missed"),missedRender:p(e.missedRender,"capture stats.missedRender"),missedCompute:p(e.missedCompute,"capture stats.missedCompute"),...Array.isArray(e.missedKeys)&&e.missedKeys.every(n=>typeof n=="string")?{missedKeys:e.missedKeys.slice(0,O)}:{}};if(r.renderBuilds+r.computeBuilds!==r.buildCalls||r.registeredRenderBuilds+r.registeredComputeBuilds!==r.registeredBuilds||r.injectedRender+r.injectedCompute!==r.injected||r.missedRender+r.missedCompute!==r.missed||r.registeredBuilds>r.buildCalls||Math.abs(r.syncBuildMs+r.asyncBuildElapsedMs-r.buildMs)>.001||r.maxSyncBuildMs>r.syncBuildMs+.001||r.maxPrecompiledSetupMs>r.precompiledSetupMs+.001||r.maxHydrationMs>r.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return r}a(Re,"captureStats");function Me(e){if(!Array.isArray(e)||e.length>O)throw new Error("Shader capture skipped builds are invalid.");return e.map((r,n)=>{if(!a$1(r)||r.kind!=="render"&&r.kind!=="compute")throw new Error(`Shader capture skipped build ${n} is invalid.`);return {kind:r.kind,name:W(r.name,`skipped build ${n} name`,512),reason:W(r.reason,`skipped build ${n} reason`)}})}a(Me,"skippedBuilds");function ke(e){let r=0,n=0,t=0,i=0;for(let s of Object.values(e.entries)){let o=e.states[s];o!==void 0&&((o.vertex!==null||o.fragment!==null)&&r++,o.vertex!==null&&n++,o.fragment!==null&&t++,o.compute!==null&&i++);}return {render:r,vertex:n,fragment:t,compute:i}}a(ke,"shaderCoverage");function Le(e,r){if(!a$1(e))throw new Error("Shader capture payload must be an object.");if(e.scene!==r.scene)throw new Error(`Shader capture scene does not match "${r.scene}".`);if(e.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let n=r.backend??"webgpu",t=v(r.runtime.three,n);if(e.compatibility!==t)throw new Error(`Shader capture compatibility must be "${t}".`);if(!a$1(e.entries))throw new Error("Shader capture entries must be an object.");if(typeof e.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let i=Object.keys(e.entries).length;if(i>O)throw new Error(`Shader capture must contain at most ${O} entries.`);if(!Array.isArray(e.errors)||e.errors.length>Ee)throw new Error("Shader capture errors are invalid.");let s=e.errors.map((w,a)=>W(w,`capture error ${a}`,64*1024));if(s.length>0)throw new Error(`Shader capture failed:
3
3
  - ${s.join(`
4
4
  - `)}`);let o=Me(e.skipped);if(i===0&&(n!=="webgl"||o.length===0))throw new Error("Shader capture must contain an entry unless WebGL explicitly skipped every live build.");let u=Re(e.stats),l=a$1(e.timing)?e.timing:void 0,g=l===void 0?void 0:Object.fromEntries(["launch","firstRequest","readiness","lastBuild","settled","posted"].flatMap(w=>{let a=l[w];if(a===void 0)return [];if(typeof a!="number"||!Number.isFinite(a)||a<0)throw new Error(`Shader capture timing.${w} is invalid.`);return [[w,a]]})),m;if(e.provenance!==void 0){if(!a$1(e.provenance)||typeof e.provenance.userAgent!="string"||e.provenance.userAgent.length>1024||typeof e.provenance.adapter!="string"||e.provenance.adapter.length>1024||!Array.isArray(e.provenance.features)||e.provenance.features.length>256||!e.provenance.features.every(w=>typeof w=="string"&&w.length<=128))throw new Error("Shader capture provenance is invalid.");m={userAgent:e.provenance.userAgent,adapter:e.provenance.adapter,features:[...new Set(e.provenance.features)].sort()};}let R=parsePrecompiledManifest({version:PRECOMPILED_MANIFEST_VERSION,scene:r.scene,three:r.runtime.three,threeBlocks:r.runtime.threeBlocks,runtime:{id:t,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},...e.automatic===void 0?{}:{automatic:e.automatic},requiresSetup:e.requiresSetup,modules:e.modules,nodes:e.nodes,layouts:e.layouts,attributePlans:e.attributePlans,updatePlans:e.updatePlans,requirementPlans:e.requirementPlans,states:e.states,entries:e.entries,...e.fallbacks===void 0?{}:{fallbacks:e.fallbacks}}),S=ke(R);if(u.registeredRenderBuilds<S.render||u.registeredComputeBuilds<S.compute)throw new Error("Shader capture did not live-build every distinct registered render/compute entry.");return {scene:r.scene,backend:n,manifest:R,skipped:o,stats:u,coverage:S,...g===void 0?{}:{timing:g},...m===void 0?{}:{provenance:m}}}a(Le,"validateShaderCapture");function E(e,r=0){let n=" ".repeat(r),t=" ".repeat(r+1);if(Array.isArray(e))return e.length===0?"[]":e.every(s=>s===null||["number","string","boolean"].includes(typeof s))?JSON.stringify(e):`[
5
5
  ${e.map(s=>`${t}${E(s,r+1)}`).join(`,