@liveroom-tech/react-immersive 6.1.1 → 6.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{SequencesTab-LWGOVQ6Y.mjs → SequencesTab-JTIVIZJD.mjs} +1 -1
- package/dist/binding-builder.css +1 -1
- package/dist/binding-builder.d.mts +3 -3
- package/dist/binding-builder.d.ts +3 -3
- package/dist/binding-builder.js +34 -27
- package/dist/binding-builder.mjs +1 -1
- package/dist/chunk-35UERL2D.mjs +83 -0
- package/dist/{chunk-DEFZEXTA.mjs → chunk-5XII5XCD.mjs} +1 -1
- package/dist/{chunk-EV6THDXD.mjs → chunk-6Q6YZ7O5.mjs} +1 -1
- package/dist/{chunk-KNCABWVN.mjs → chunk-DS5XNP7A.mjs} +2 -2
- package/dist/chunk-M4LVNNVP.mjs +1 -0
- package/dist/chunk-Q4QPI5GG.mjs +9 -0
- package/dist/{chunk-MLT4JQAY.mjs → chunk-W7M2YD65.mjs} +1 -1
- package/dist/{chunk-Z2VQGUC2.mjs → chunk-WJIICFV4.mjs} +2 -2
- package/dist/{chunk-5PJ5MLKE.mjs → chunk-XBVAZFXW.mjs} +1 -1
- package/dist/hosted.css +1 -1
- package/dist/hosted.d.mts +3 -3
- package/dist/hosted.d.ts +3 -3
- package/dist/hosted.js +33 -26
- package/dist/hosted.mjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +31 -24
- package/dist/index.mjs +1 -1
- package/dist/{modelFileResolver-B8ADn9Nl.d.mts → modelFileResolver-pPzMl63D.d.mts} +6 -0
- package/dist/{modelFileResolver-B8ADn9Nl.d.ts → modelFileResolver-pPzMl63D.d.ts} +6 -0
- package/dist/{modelViewerProps-BE4D56Ti.d.ts → modelViewerProps-07WgBVqm.d.ts} +4 -2
- package/dist/{modelViewerProps-DBwh-fmu.d.mts → modelViewerProps-CGgtm4Zb.d.mts} +4 -2
- package/dist/{publicProps-Clr1nSE6.d.mts → publicProps-BylAVwPu.d.mts} +1 -1
- package/dist/{publicProps-3LNTAskZ.d.ts → publicProps-CEt3hxQU.d.ts} +1 -1
- package/dist/simple-model-viewer.d.mts +2 -2
- package/dist/simple-model-viewer.d.ts +2 -2
- package/dist/simple-model-viewer.js +1 -1
- package/dist/simple-model-viewer.mjs +1 -1
- package/dist/utils.d.mts +4 -4
- package/dist/utils.d.ts +4 -4
- package/dist/utils.js +9 -2
- package/dist/utils.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-5FLX45O5.mjs +0 -2
- package/dist/chunk-644OGSQJ.mjs +0 -83
- package/dist/chunk-OPDRK3GS.mjs +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as Nd,b as Ad}from"./chunk-E24EFHB5.mjs";import{a as vn}from"./chunk-FXV4CLAK.mjs";import{a as hn,b as xn,c as to,d as Pd,e as ma,g as oe,h as se,i as Bd,j as Td,k as O,l as be,m as st,n as Rd,o as pt,p as kt,q as $o}from"./chunk-AL6UIGWP.mjs";import{A as xd,B as vd,C as Md,a as Rl,b as la,d as qi,f as Yl,g as fn,h as Ji,i as Zl,j as Ql,k as pa,l as nd,o as sd,p as ld,q as dd,r as cd,s as pd,t as ud,u as bd,v as gd,w as ba,x as md,y as hd}from"./chunk-644OGSQJ.mjs";import{a as ed,b as ua,c as nt,d as td,e as St,f as Ho,g as od,h as it,i as We}from"./chunk-FGAJ2UT7.mjs";import{B as ql,C as Xl,T as rd,h as sa,k as ho}from"./chunk-KNCABWVN.mjs";import{a as id}from"./chunk-37YITTIK.mjs";import{A as Il,B as Wn,C as zl,D as fo,Da as Yn,E as Ll,Fa as Xi,Ga as ad,H as Vi,Ha as fd,I as Do,Ia as ga,Ja as yd,Ka as wd,L as Fo,La as Sd,M as Dl,Ma as kd,N as Fl,Na as Cd,O as Hl,a as Ui,ca as Ki,e as Gn,fa as mn,ia as Vl,j as gn,k as $t,l as It,m as qn,ta as da,ua as Wi,v as Nl,va as Yi,w as Al,x as Ol,xa as ca,y as El,ya as Wl,z as jl}from"./chunk-5FLX45O5.mjs";import{e as _i}from"./chunk-LX3GXQNU.mjs";import{p as Gi}from"./chunk-7JCFNZJM.mjs";import{k as Kl,n as Gl,t as Jl}from"./chunk-EV6THDXD.mjs";import{c as $l,d as Ul,g as _l,h as aa}from"./chunk-BNKTI3CY.mjs";function xo(e){return{annotations:e.annotations,animations:e.animations,activeVariants:e.model.activeVariants,measurements:e.measurements,selectionSets:e.selectionSets,product:e.product,sequences:e.sequences}}function Xe(e,t){return{...e,model:{...e.model,activeVariants:t?.activeVariants??[]},annotations:t?.annotations??[],animations:t?.animations??fo.animations,measurements:t?.measurements,selectionSets:t?.selectionSets,product:t?.product,sequences:t?.sequences}}function Ed(e){if(e===void 0)return!0;try{return Gi(e),!0}catch{return!1}}function jd(e){if(e===void 0)return!0;try{return mn(e),!0}catch{return!1}}function Id(e){if(e===void 0)return!0;try{return Ki(e),!0}catch{return!1}}var Hg="react-immersive:binding-builder",$g=2,vo="session",yo="model",wo="textures",ha="current",zd=1;function Ut(e){return e.kind==="file"?`file:${e.key}`:`url:${e.url}`}var Uo=null;function Jn(){return Uo||(Uo=new Promise((e,t)=>{if(typeof indexedDB>"u"){t(new Error("IndexedDB is not available in this environment."));return}let i=indexedDB.open(Hg,$g);i.onupgradeneeded=()=>{let a=i.result;a.objectStoreNames.contains(vo)||a.createObjectStore(vo),a.objectStoreNames.contains(yo)||a.createObjectStore(yo),a.objectStoreNames.contains(wo)||a.createObjectStore(wo)},i.onsuccess=()=>{let a=i.result;a.onversionchange=()=>{a.close(),Uo=null},e(a)},i.onerror=()=>t(i.error??new Error("Failed to open IndexedDB."))}),Uo.catch(()=>{Uo=null}),Uo)}function yn(e){return new Promise((t,i)=>{e.oncomplete=()=>t(),e.onerror=()=>i(e.error??new Error("IndexedDB transaction failed.")),e.onabort=()=>i(e.error??new Error("IndexedDB transaction aborted."))})}function xa(e){return new Promise((t,i)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>i(e.error??new Error("IndexedDB request failed."))})}function lt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function va(e){return!lt(e)||typeof e.name!="string"?!1:e.kind==="file"?typeof e.key=="string":e.kind==="url"?typeof e.url=="string":!1}function Ld(e){return lt(e)&&va(e.model)&&typeof e.namePrefix=="string"}function Ug(e){if(e===void 0)return!0;try{return Ll(e),!0}catch{return!1}}function Dd(e){if(e===void 0)return!0;try{return _i(e),!0}catch{return!1}}function _g(e){return!lt(e)||!va(e.model)||!lt(e.bindings)||!lt(e.originalTransforms)||e.modelSettings!==void 0&&(!lt(e.modelSettings)||!Array.isArray(e.modelSettings.annotations)||!lt(e.modelSettings.animations)||!Array.isArray(e.modelSettings.animations.clips)||e.modelSettings.activeVariants!==void 0&&(!Array.isArray(e.modelSettings.activeVariants)||!e.modelSettings.activeVariants.every(t=>typeof t=="string")))||lt(e.modelSettings)&&!Id(e.modelSettings.measurements)||lt(e.modelSettings)&&!jd(e.modelSettings.selectionSets)||lt(e.modelSettings)&&!Ed(e.modelSettings.product)||lt(e.modelSettings)&&!Dd(e.modelSettings.sequences)?!1:e.mergeModels===void 0?!0:Array.isArray(e.mergeModels)&&e.mergeModels.every(Ld)}function Zi(e){if(!lt(e)||e.version!==zd)return!1;if(e.composition!==void 0)try{Fo(e.composition)}catch{return!1}return!(typeof e.savedAt!="number"||!lt(e.bindings)||!lt(e.sceneConfig)||!va(e.model)||!Id(e.sceneConfig.measurements)||!jd(e.sceneConfig.selectionSets)||!Ed(e.sceneConfig.product)||!Dd(e.sceneConfig.sequences)||!Ug(e.sceneConfig.section)||e.parkedModels!==void 0&&(!Array.isArray(e.parkedModels)||!e.parkedModels.every(_g))||e.mergeModels!==void 0&&(!Array.isArray(e.mergeModels)||!e.mergeModels.every(Ld))||e.modelOrder!==void 0&&(!Array.isArray(e.modelOrder)||!e.modelOrder.every(t=>typeof t=="string")))}function fa(e,t){return e.kind==="url"?Promise.resolve(null):xa(t.get(e.key)).then(i=>!i||i.key!==e.key?null:new File([i.blob],i.name,{type:i.type,lastModified:i.lastModified}))}async function Fd(e,t){let i=await Jn(),a={...e,version:zd,savedAt:Date.now()},o=i.transaction([vo,yo],"readwrite"),n=yn(o);o.objectStore(vo).put(a,ha);let d=o.objectStore(yo),s=new Set,p=x=>{x.kind==="file"&&s.add(x.key)};p(a.model),a.mergeModels?.forEach(x=>p(x.model)),a.parkedModels?.forEach(x=>{p(x.model),x.mergeModels?.forEach(h=>p(h.model))});for(let{key:x,file:h}of t??[]){let g={key:x,blob:h,name:h.name,type:h.type,lastModified:h.lastModified};d.put(g,x)}let c=d.getAllKeys();return c.onsuccess=()=>{for(let x of c.result)s.has(x)||d.delete(x)},await n,a}function Od(e,t){return Promise.all(e.map(async i=>({entry:i,file:await fa(i.model,t)})))}async function Hd(){let e=await Jn(),t=e.transaction(vo,"readonly"),i=yn(t),a=await xa(t.objectStore(vo).get(ha));if(await i,!Zi(a))return null;let o=a.parkedModels??[],n=a.mergeModels??[],d=e.transaction(yo,"readonly"),s=yn(d),p=d.objectStore(yo),[c,x,h]=await Promise.all([fa(a.model,p),Od(n,p),Promise.all(o.map(async g=>({entry:g,file:await fa(g.model,p),mergeFiles:await Od(g.mergeModels??[],p)})))]);return await s,a.model.kind==="file"&&!c?null:{session:{...a,parkedModels:o,mergeModels:n},file:c,parkedFiles:h,mergeFiles:x}}async function $d(){let t=(await Jn()).transaction([vo,yo,wo],"readwrite"),i=yn(t);t.objectStore(vo).delete(ha),t.objectStore(yo).clear(),t.objectStore(wo).clear(),await i}async function wn(e,t){let a=(await Jn()).transaction(wo,"readwrite"),o=yn(a),n={blob:t,name:t.name,type:t.type,savedAt:Date.now()};a.objectStore(wo).put(n,e),await o}async function oo(e){let i=(await Jn()).transaction(wo,"readonly"),a=yn(i),o=await xa(i.objectStore(wo).get(e));return await a,o?new File([o.blob],o.name,{type:o.type,lastModified:o.savedAt}):null}function Vo(e){return`url:${e}`}function wa(e){return e.models.find(t=>!e.composition.placements[Vo(t.url)]?.deleted)??e.models[0]}function Sa(e){return Fo(e.composition)}function er(e,t){return Xe(e,t.modelSettings)}function Vg(e){return{url:e.url,namePrefix:e.namePrefix,resolved:{url:e.url,name:e.namePrefix,format:"glb",cleanup:()=>{}},sessionModel:{kind:"url",url:e.url,name:e.namePrefix},nodeNames:[],loadState:"loading"}}function Sn(e){return(e.mergeModels??[]).map(Vg)}function ka(e){let t=e.name??"model";return{url:e.url,name:t,bindings:e.objectBindings,originalTransforms:{},sessionModel:{kind:"url",url:e.url,name:t},mergedModelSources:Sn(e),modelSettings:e.modelSettings}}function Ca(e){let t=new Map;for(let i of e.models){let{url:a,name:o,assetId:n,tilesetUrl:d,assetVersion:s}=i;t.set(a,{url:a,name:o,assetId:n,tilesetUrl:d,assetVersion:s});for(let p of i.mergeModels??[])t.set(p.url,{url:p.url,assetId:p.assetId})}return t}function Ud(e){let t=a=>a.map(o=>({url:o.url,assetId:e.sources.get(o.url)?.assetId??null,namePrefix:o.namePrefix})),i=e.modelOrder.flatMap(a=>{if(e.composition.placements[Vo(a)]?.deleted)return[];let o=e.sources.get(a)??{url:a};if(a===e.modelUrl)return[{...o,url:a,name:e.modelName,objectBindings:e.bindings,mergeModels:t(e.mergedModelSources),modelSettings:xo(e.sceneConfig)}];let n=e.parkedModels.find(d=>d.url===a);return n?[{...o,url:a,name:n.name,objectBindings:n.bindings,mergeModels:t(n.mergedModelSources),modelSettings:n.modelSettings}]:[]});return{projectId:e.project.id,baseRevision:e.project.revision,models:i,composition:{...e.composition,placements:Object.fromEntries(Object.entries(e.composition.placements).filter(([,a])=>!a.deleted))},sceneConfig:Xe(e.sceneConfig)}}function ya(e){return JSON.stringify(e,(t,i)=>i&&typeof i=="object"&&!Array.isArray(i)?Object.fromEntries(Object.entries(i).sort(([a],[o])=>a<o?-1:a>o?1:0)):i)}function tr(e,t){return e===t||ya(e)===ya(t)}function Kg(e){return xo(Xe(fo,e))}function kn(e){return ya({models:e.models.map(t=>({url:t.url,name:t.name,objectBindings:t.objectBindings,mergeModels:(t.mergeModels??[]).map(({url:i,namePrefix:a})=>({url:i,namePrefix:a})),modelSettings:Kg(t.modelSettings)})),composition:e.composition,sceneConfig:Xe(e.sceneConfig)})}function xv(e){if(!(e.models.length<2))return e.models.flatMap(t=>{let i=e.composition.placements[Vo(t.url)]??{};return i.deleted?[]:[{url:t.url,label:i.label??t.name,transform:i,visible:i.visible!==!1,objectBindings:t.objectBindings,sceneConfig:er(e.sceneConfig,t),mergeModels:t.mergeModels?.map(({url:a,namePrefix:o})=>({url:a,namePrefix:o}))}]})}var _d=new Set(["path","image","url","poster","src","imageUrl"]);function Gg(e){return e.startsWith("blob:")||e.startsWith("data:")||!!$t(e)}function _o(e,t=new Set){if(Array.isArray(e))e.forEach(i=>_o(i,t));else if(e&&typeof e=="object")for(let[i,a]of Object.entries(e))typeof a=="string"?_d.has(i)&&Gg(a)&&t.add(a):_o(a,t);return t}function Qi(e,t){return Array.isArray(e)?e.map(i=>Qi(i,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([i,a])=>[i,typeof a=="string"&&_d.has(i)&&t.has(a)?t.get(a):Qi(a,t)])):e}async function Vd(e){let t=$t(e)??e,i=await(await fetch(t)).blob(),a=e.startsWith("blob:")||e.startsWith("data:")?"image":e.split("/").pop()||"image";return new File([i],a,{type:i.type})}async function Kd(e,t){let i=x=>e.session.composition?.placements[Ut(x)]?.deleted;e={...e,parkedFiles:e.parkedFiles.filter(x=>!i(x.entry.model))};let a=new Map,o=async(x,h)=>{if(x.kind!=="file")return x;if(!h)throw new Error(`The scene bundle is missing ${x.name}.`);let{url:g}=await t(h);return a.set(`file:${x.key}`,Vo(g)),{kind:"url",url:g,name:x.name}},n=async x=>{let h=[];for(let{entry:g,file:C}of x)h.push({entry:{...g,model:await o(g.model,C)},file:null});return h},d=await o(e.session.model,e.file),s=await n(e.mergeFiles),p=[];for(let x of e.parkedFiles){let h=await o(x.entry.model,x.file),g=await n(x.mergeFiles);p.push({entry:{...x.entry,model:h,mergeModels:g.map(C=>C.entry)},file:null,mergeFiles:g})}let c=e.session.composition;return{file:null,mergeFiles:s,parkedFiles:p,session:{...e.session,model:d,mergeModels:s.map(x=>x.entry),parkedModels:p.map(x=>x.entry),modelOrder:e.session.modelOrder?.map(x=>a.get(x)??x),composition:c&&{...c,placements:Object.fromEntries(Object.entries(c.placements).map(([x,h])=>[a.get(x)??x,h]))}}}}import{strFromU8 as qg,strToU8 as Wg,unzip as Yg}from"fflate";var Xn=512*1024*1024,Gd=5*1024*1024;function Ma(e){return[e.model,...(e.mergeModels??[]).map(t=>t.model),...(e.parkedModels??[]).flatMap(t=>[t.model,...(t.mergeModels??[]).map(i=>i.model)])]}function qd(e){let t=o=>o.kind==="file"?`/bundle/${encodeURIComponent(o.key)}.glb`:o.url,i=[{model:e.model,bindings:e.bindings,merges:e.mergeModels,config:e.sceneConfig},...(e.parkedModels??[]).map(o=>({model:o.model,bindings:o.bindings,merges:o.mergeModels,config:Xe(e.sceneConfig,o.modelSettings)}))],a=i.map(o=>o.model.kind==="file"?`file:${o.model.key}`:`url:${o.model.url}`);if(new Set(a).size!==a.length||i.length>256)throw new Error("Scene instances must have unique identities (maximum 256).");if(e.modelOrder&&(new Set(e.modelOrder).size!==e.modelOrder.length||e.modelOrder.some(o=>!a.includes(o))))throw new Error("Invalid scene asset order.");for(let o of e.parkedModels??[])for(let n of Object.values(o.originalTransforms))for(let d of["position","rotation","scale"]){let s=n?.[d];if(s!==void 0&&(!Array.isArray(s)||s.length!==3||!s.every(p=>typeof p=="number"&&Number.isFinite(p))))throw new Error("Invalid original node transform.")}for(let o of i)Vl({version:1,objectBindings:o.bindings,configuration:{modelUrl:t(o.model),sceneConfig:o.config,mergeModels:o.merges?.map(n=>({url:t(n.model),namePrefix:n.namePrefix}))}})}async function Wd(e,t){let i=JSON.parse(JSON.stringify({...e,version:1,savedAt:Date.now()})),a={},o=[],n=[],d=0;async function s(g,C){if(d+=C.size,d>Xn)throw new Error("Scene bundle exceeds the 512 MiB expanded limit.");a[g]=new Uint8Array(await C.arrayBuffer())}for(let g of Ma(i)){if(g.kind!=="file"||o.some(y=>y.key===g.key))continue;let C=t.get(g.key);if(!C)throw new Error(`Cannot save scene: missing uploaded file ${g.name}.`);let M=`models/${o.length}`;o.push({key:g.key,path:M,name:C.name,type:C.type,lastModified:C.lastModified}),await s(M,C)}let p=new Map;async function c(g,C=0){if(C>64)throw new Error("Scene data is too deeply nested.");if(!(!g||typeof g!="object"))for(let[M,y]of Object.entries(g)){if(["__proto__","prototype","constructor"].includes(M))throw new Error("Reserved scene property.");if(M!=="metadata")if(typeof y=="string"){if(!["path","image","url","poster","src","imageUrl","customEnvironmentUrl"].includes(M))continue;let T=$t(y),f=T||y.startsWith("blob:")||y.startsWith("data:")?null:await oo(y);if(!f&&!T&&!y.startsWith("blob:")&&!y.startsWith("data:"))continue;let u=p.get(y);if(u){g[M]=u;continue}if(!f){let N=await fetch(T??y);if(!N.ok)throw new Error("Cannot read an uploaded texture for this scene.");let A=await N.blob();f=new File([A],`texture-${n.length}`,{type:A.type})}let v=`textures/${n.length}`,m=`/__ri_bundle_texture__/${n.length}`;n.push({ref:m,path:v,name:f.name,type:f.type}),await s(v,f),p.set(y,m),g[M]=m}else await c(y,C+1)}}for(let g of Ma(i))if(g.kind==="url"&&g.url.startsWith("blob:"))throw new Error("Cannot save a temporary model URL without its original file.");if(await c(i),!Zi(i))throw new Error("Invalid scene snapshot.");qd(i);let x=Wg(JSON.stringify({format:"react-immersive-scene",version:1,session:i,files:o,textures:n}));if(x.byteLength>Gd)throw new Error("Scene settings exceed the 5 MiB limit.");if(d+x.byteLength>Xn||Object.keys(a).length+1>1024)throw new Error("Scene bundle exceeds its size or file-count limit.");a["scene.json"]=x;let h=await Ji(a);if(h.byteLength>Xn)throw new Error("Compressed scene bundle exceeds 512 MiB.");return new Blob([h],{type:"application/zip"})}async function Yd(e){if(e.size>Xn)throw new Error("Scene ZIP exceeds 512 MiB.");let t=0,i=0,a="",o=new Set,n=new Uint8Array(await e.arrayBuffer()),d=await new Promise((y,T)=>Yg(n,{filter(f){return t+=f.originalSize,i++,o.has(f.name)?(a="Duplicate scene ZIP entry.",!1):(o.add(f.name),i>1024||t>Xn||f.name==="scene.json"&&f.originalSize>Gd||!/^(scene\.json|models\/\d+|textures\/\d+)$/.test(f.name)?(a="Invalid or oversized scene ZIP entries.",!1):!0)}},(f,u)=>f?T(f):a?T(new Error(a)):y(u)));if(!d["scene.json"])throw new Error("This ZIP does not contain a React Immersive scene.");let s=JSON.parse(qg(d["scene.json"]));if(s.format!=="react-immersive-scene"||s.version!==1||!Zi(s.session)||!Array.isArray(s.files)||!Array.isArray(s.textures))throw new Error("Invalid scene bundle manifest.");qd(s.session);let p=new Map,c=new Set;for(let y of s.files){if(!y||typeof y.key!="string"||!/^models\/\d+$/.test(y.path)||!d[y.path]||typeof y.name!="string"||typeof y.type!="string"||!Number.isFinite(y.lastModified)||c.has(y.path)||p.has(y.key))throw new Error("Invalid model file in scene bundle.");c.add(y.path),p.set(y.key,new File([d[y.path]],y.name,{type:y.type,lastModified:y.lastModified}))}for(let y of Ma(s.session))if(y.kind==="file"&&!p.has(y.key))throw new Error(`Scene bundle is missing ${y.name}.`);let x=new Map,h=crypto.randomUUID();for(let y of s.textures){if(!y||typeof y.ref!="string"||!/^\/__ri_bundle_texture__\/\d+$/.test(y.ref)||!/^textures\/\d+$/.test(y.path)||!d[y.path]||typeof y.name!="string"||typeof y.type!="string"||c.has(y.path)||x.has(y.ref))throw new Error("Invalid texture in scene bundle.");c.add(y.path),x.set(y.ref,{path:`materials/scene-${h}/${x.size}`,file:new File([d[y.path]],y.name,{type:y.type})})}function g(y,T=0){if(T>64)throw new Error("Scene data is too deeply nested.");if(!(!y||typeof y!="object"))for(let[f,u]of Object.entries(y)){if(["__proto__","constructor","prototype"].includes(f))throw new Error("Reserved scene property.");if(f!=="metadata")if(typeof u=="string"&&u.startsWith("/__ri_bundle_texture__/")){let v=x.get(u);if(!v)throw new Error("Scene bundle is missing a texture.");if(f==="path")y[f]=v.path;else{let m=d[[...s.textures].find(A=>A.ref===u).path],N="";for(let A=0;A<m.length;A+=32768)N+=String.fromCharCode(...m.subarray(A,A+32768));y[f]=`data:${v.file.type||"application/octet-stream"};base64,${btoa(N)}`}}else g(u,T+1)}}g(s.session),await Promise.all([...x.values()].map(y=>wn(y.path,y.file)));let C=y=>y.kind==="file"?p.get(y.key):null,M=y=>y.map(T=>({entry:T,file:C(T.model)}));return{session:s.session,file:C(s.session.model),mergeFiles:M(s.session.mergeModels??[]),parkedFiles:(s.session.parkedModels??[]).map(y=>({entry:y,file:C(y.model),mergeFiles:M(y.mergeModels??[])}))}}import{useCallback as Z,useEffect as ze,useMemo as Ue,useRef as ne,useState as U}from"react";import{Box3 as Su,Vector3 as Ox}from"three";import{Box as Ex,ChevronDown as jx,ClipboardPaste as Ix,Copy as zx,Ellipsis as Lx,Eye as Dx,PanelLeftClose as Fx,PanelLeftOpen as Hx,PanelRightClose as $x,PanelRightOpen as Ux,Pin as _x,PinOff as Vx,Trash2 as Kx}from"lucide-react";import{useEffect as Jg,useId as Xg,useRef as Jd,useState as Xd}from"react";import{Check as Zg,ChevronDown as Qg,History as em,ListRestart as tm,Plus as om,Trash2 as nm,Upload as im}from"lucide-react";import{Fragment as Qd,jsx as dt,jsxs as Ct}from"react/jsx-runtime";function Zn({label:e,icon:t,title:i,align:a="left",children:o}){let[n,d]=Xd(!1),s=Jd(null),p=Jd(null),c=Xg();return Jg(()=>{if(!n)return;let x=g=>{s.current?.contains(g.target)||d(!1)},h=g=>{g.key==="Escape"&&(d(!1),p.current?.focus())};return window.addEventListener("pointerdown",x),window.addEventListener("keydown",h),()=>{window.removeEventListener("pointerdown",x),window.removeEventListener("keydown",h)}},[n]),Ct("div",{className:"bb-headerMenuWrapper",ref:s,children:[Ct("button",{ref:p,type:"button",className:`bb-headerButton ${e?"":"bb-headerButton--icon"} ${n?"bb-headerButton--open":""}`,onClick:()=>d(x=>!x),title:i,"aria-label":e?void 0:i,"aria-expanded":n,"aria-controls":n?c:void 0,children:[t,e?Ct(Qd,{children:[e,dt(Qg,{size:12,"aria-hidden":"true"})]}):null]}),n?dt("div",{id:c,className:`bb-headerMenu bb-headerMenu--${a}`,role:"group","aria-label":i,children:o(()=>d(!1))}):null]})}function Zd({models:e,activeModelUrl:t,onSelectModel:i,onRestore:a,onRemove:o,onAddModel:n,onUpload:d,onReset:s,resetLabel:p,restoreDisabled:c,addModelDisabled:x,confirmRemove:h=!0,close:g}){let[C,M]=Xd(!1);return C&&o?Ct("div",{className:"bb-headerMenuConfirm",role:"alertdialog","aria-label":"Remove model",children:[dt("p",{children:"Remove the model and its bindings from the editor? This also clears the saved session. Export your work first if you want to keep it."}),Ct("div",{className:"bb-headerMenuConfirmActions",children:[dt("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>M(!1),children:"Cancel"}),dt("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{g(),o()},autoFocus:!0,children:"Remove"})]})]}):Ct(Qd,{children:[e?dt("div",{className:"bb-modelMenuList",role:"radiogroup","aria-label":"Active model",children:e.map(y=>Ct("button",{type:"button",role:"radio","aria-checked":y.url===t,className:"bb-headerMenuItem bb-modelMenuItem",title:y.label,onClick:()=>{g(),i?.(y.url)},children:[dt("span",{className:"bb-modelMenuCheck",children:y.url===t?dt(Zg,{size:14,"aria-hidden":"true"}):null}),dt("span",{className:"bb-modelMenuName",children:y.label})]},y.url))}):null,d?Ct("button",{type:"button",className:"bb-headerMenuItem",disabled:x,onClick:()=>{g(),d()},children:[dt(im,{size:14,"aria-hidden":"true"}),"Open model\u2026"]}):null,n?Ct("button",{type:"button",className:"bb-headerMenuItem",disabled:x,onClick:()=>{g(),n()},title:"Add another model, as a separate model or merged into this one",children:[dt(om,{size:14,"aria-hidden":"true"}),"Add model\u2026"]}):null,a?Ct("button",{type:"button",className:"bb-headerMenuItem",disabled:c,onClick:()=>{g(),a()},title:"Restore your last session: the model, its object bindings, and scene settings saved in this browser",children:[dt(em,{size:14,"aria-hidden":"true"}),"Restore last session"]}):null,s?Ct("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>{g(),s()},children:[dt(tm,{size:14,"aria-hidden":"true"}),p]}):null,o?Ct("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{if(h){M(!0);return}g(),o()},children:[dt(nm,{size:14,"aria-hidden":"true"}),"Remove model\u2026"]}):null]})}import{useCallback as rm,useEffect as am,useMemo as sm,useRef as ec}from"react";import{jsx as Pa,jsxs as lm}from"react/jsx-runtime";function tc({liveViewerRef:e,renderBefore:t,split:i,onSplitChange:a,labels:o,beforeAction:n,report:d,selected:s,onSelect:p,matchBy:c,onMatchByChange:x,showOutlines:h,onShowOutlinesChange:g}){let C=ec(null),M=ec(null),y=sm(()=>hd(),[]);am(()=>()=>y.detach(),[y]);let T=rm(f=>{M.current=f;let u=e.current;u&&y.attach(0,u.raw.controls,u.invalidate),y.attach(1,f.raw.controls,f.invalidate)},[y,e]);return lm("div",{ref:C,className:"ri-compare ri-compare--overlay",style:{"--ri-compare-split":`${i*100}%`},children:[Pa("div",{className:"ri-compare__layer ri-compare__layer--before",children:t(T)}),d&&Pa(md,{showOutlines:h,onShowOutlinesChange:g,matchBy:c,onMatchByChange:x,report:d,selected:s,onClear:()=>p?.(null),onSelect:f=>{let u=f.afterObjectId?0:1,v=u===0?e.current:M.current,m=u===0?f.afterObjectId:f.beforeObjectId,N=m?v?.raw.nodes[m]:null;y.setLeader(u),p?.(f),v&&N&&(v.raw.controls.fitToBox(N,!0),v.invalidate())}}),Pa(xd,{split:i,onSplitChange:a,labels:o,containerRef:C,beforeAction:n})]})}import{useCallback as no,useEffect as oc,useMemo as nc,useRef as or,useState as ic}from"react";var dm={currentClip:null,isPlaying:!1,speed:1,time:0,duration:0,active:[]};function cm(e,t){let i=[],a=new Map,o=new Map,n=new Map,d=new Set;for(let s of e){let p=t.get(s);if(!p)continue;let c=p.clipDetails??p.clips.map(h=>({sourceName:h,duration:0}));n.set(s,c);let x=new Map;for(let h of c){let g=h.sourceName;for(let C=2;d.has(g);C+=1)g=`${h.sourceName} (${C})`;d.add(g),i.push({sourceName:g,duration:h.duration}),a.set(g,{url:s,sourceName:h.sourceName}),x.set(h.sourceName,g)}o.set(s,x)}return{clipDetails:i,targets:a,displayNamesByUrl:o,clipDetailsByUrl:n}}function pm(e,t,i){let a=[];for(let o of e){let n=t.get(o),d=i.get(o);if(!(!n||!d))for(let s of n.active){let p=d.get(s.clip);p&&a.push({...s,clip:p})}}return a}function rc(e){let t=or(new Map),i=or(new Map),a=or(new Map),[o,n]=ic(0),[d,s]=ic(0),p=no((B,P)=>{if(t.current.get(B)===P)return;a.current.get(B)?.(),a.current.delete(B),t.current.set(B,P),i.current.set(B,P.getState?.()??dm);let $=P.subscribe?.(H=>{i.current.set(B,H),s(de=>de+1)});$&&a.current.set(B,$),n(H=>H+1)},[]);oc(()=>{let B=new Set(e),P=!1;for(let $ of[...t.current.keys()])B.has($)||(a.current.get($)?.(),a.current.delete($),t.current.delete($),i.current.delete($),P=!0);P&&n($=>$+1)},[e]),oc(()=>()=>a.current.forEach(B=>B()),[]);let{clipDetails:c,targets:x,displayNamesByUrl:h,clipDetailsByUrl:g,hasModels:C}=nc(()=>({...cm(e,t.current),hasModels:t.current.size>0}),[e,o]),M=or(x);M.current=x;let y=nc(()=>pm(e,i.current,h),[e,h,d]),T=no((B,P,$)=>{$(),!P.subscribe&&P.getState&&(i.current.set(B,P.getState()),s(H=>H+1))},[]),f=no(B=>{t.current.forEach((P,$)=>T($,P,()=>B(P,$)))},[T]),u=no((B,P)=>{let $=M.current.get(B);if(!$)return;let H=t.current.get($.url);H&&T($.url,H,()=>P(H,$))},[T]),v=no((B,P)=>u(B,($,H)=>$.play(H.sourceName,P)),[u]),m=no(B=>B===void 0?f(P=>P.pause()):u(B,(P,$)=>P.pause($.sourceName)),[f,u]),N=no(B=>B===void 0?f(P=>P.stop()):u(B,(P,$)=>P.stop($.sourceName)),[f,u]),A=no((B,P)=>P===void 0?f($=>$.setSpeed(B)):u(P,($,H)=>$.setSpeed(B,H.sourceName)),[f,u]),G=no((B,P)=>P===void 0?f($=>$.seek?.(B)):u(P,($,H)=>$.seek?.(B,H.sourceName)),[f,u]);return{clipDetails:c,clipDetailsByUrl:g,displayNamesByUrl:h,hasModels:C,active:y,play:v,pause:m,stop:N,setSpeed:A,seek:G,handleModelAnimationsReady:p}}import{useEffect as mm,useMemo as fm}from"react";function Qn(e,t){let i=new Map(e.animations.clips.map(n=>[n.sourceName,n])),a=t.map(({sourceName:n})=>i.get(n)??{sourceName:n,displayName:n,hidden:!1,loopMode:"repeat",speed:1}),o=e.animations.autoplayClip&&a.some(n=>n.sourceName===e.animations.autoplayClip&&!n.hidden)?e.animations.autoplayClip:null;return o===e.animations.autoplayClip&&a.length===e.animations.clips.length&&a.every((n,d)=>n===e.animations.clips[d])?e.animations:{clips:a,autoplayClip:o}}function nr(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function ei(e,t){if(!nr(e)||!nr(t))return t??e;let i={...e};for(let[a,o]of Object.entries(t)){if(o===void 0)continue;if(a==="section"){i[a]=Vi(i[a],o);continue}if(a==="sequences"){i[a]=_i(o);continue}let n=i[a];i[a]=nr(n)&&nr(o)?ei(n,o):o}return i}import{useCallback as So,useReducer as um,useRef as bm}from"react";var gm=100;function io(e,t){switch(t.type){case"history":return t.updater(e);case"set":{let i=typeof t.updater=="function"?t.updater(e.present):t.updater;if(i===e.present)return e;let a=t.track?e.edits+1:e.edits,o=!t.track&&e.edits===0?i:e.baseline;return t.track?t.coalesce?{...e,present:i,future:[],edits:a,baseline:o}:{past:[...e.past,e.present].slice(-gm),present:i,future:[],edits:a,baseline:o}:{...e,present:i,baseline:o}}case"undo":{if(e.past.length===0)return e;let i=e.past[e.past.length-1];return{...e,past:e.past.slice(0,-1),present:i,future:[e.present,...e.future],edits:e.edits+1}}case"redo":{if(e.future.length===0)return e;let[i,...a]=e.future;return{...e,past:[...e.past,e.present],present:i,future:a,edits:e.edits+1}}case"reset":return{past:[],present:t.value,future:[],edits:t.track?e.edits+1:0,baseline:t.track?e.baseline:t.value}}}function ti(e,t=600){let[i,a]=um(io,{past:[],present:e,future:[],edits:0,baseline:e}),o=bm(0),n=So(C=>{let M=Date.now(),y=M-o.current<t;o.current=M,a({type:"set",updater:C,coalesce:y,track:!0})},[t]),d=So(C=>{let M=Date.now()-o.current<t;a({type:"set",updater:C,coalesce:M,track:!1})},[t]),s=So(C=>{o.current=0,a({type:"set",updater:C,coalesce:!1,track:!0})},[]),p=So(C=>{a({type:"history",updater:C})},[]),c=So(C=>{o.current=0,a({type:"history",updater:typeof C=="function"?C:()=>C})},[]),x=So(()=>{o.current=0,a({type:"undo"})},[]),h=So(()=>{o.current=0,a({type:"redo"})},[]),g=So((C,M)=>{o.current=0,a({type:"reset",value:C,track:M?.asEdit??!1})},[]);return{value:i.present,setValue:n,setValueUntracked:d,setValueAsStep:s,updateHistory:p,restoreSnapshot:c,snapshot:i,undo:x,redo:h,reset:g,canUndo:i.past.length>0,canRedo:i.future.length>0,edits:i.edits,baseline:i.baseline}}function hm(e,t){return e.sourceName===t.sourceName&&e.displayName===t.displayName&&e.hidden===t.hidden&&e.loopMode===t.loopMode&&e.speed===t.speed}function ac(e,t,i,a){let o=Xe(t,e.modelSettings);if(o.animations===i)return e;let n={...o,animations:i},d=e.sceneHistory??{past:[],present:o,future:[],baseline:o,edits:0};return{...e,modelSettings:xo(n),sceneHistory:io(d,{type:"set",updater:n,track:a,coalesce:!1})}}function sc({modelUrl:e,sceneConfig:t,setSceneConfig:i,setSceneConfigUntracked:a,parkedModels:o,setParkedModels:n,animations:d,markSessionEdited:s}){let{clipDetailsByUrl:p,displayNamesByUrl:c}=d;mm(()=>{let g=e?p.get(e):void 0;g&&a(C=>{let M=Qn(C,g);return M===C.animations?C:{...C,animations:M}}),n(C=>{let M=!1,y=C.map(T=>{let f=p.get(T.url);if(!f)return T;let u=Xe(t,T.modelSettings),v=ac(T,t,Qn(u,f),!1);return M||(M=v!==T),v});return M?y:C})},[p,e,t,a,n]);let x=fm(()=>{let g=[],C=null;for(let[M,y]of c){let T=M===e?t:Xe(t,o.find(u=>u.url===M)?.modelSettings),f=Qn(T,p.get(M)??[]);for(let u of f.clips){let v=y.get(u.sourceName);v&&g.push({...u,sourceName:v,displayName:u.displayName===u.sourceName?v:u.displayName})}C??(C=f.autoplayClip?y.get(f.autoplayClip)??null:null)}return{clips:g,autoplayClip:C}},[c,p,e,t,o]);return{config:x,onChange:g=>{let C=new Map(x.clips.map(T=>[T.sourceName,T])),M=new Map(g.clips.map(T=>[T.sourceName,T])),y=(T,f)=>{let u=c.get(T);if(!u)return f.animations;let v=Qn(f,p.get(T)??[]),m=v.clips.map(A=>{let G=u.get(A.sourceName),B=G?M.get(G):void 0;if(!B)return A;let P={...B,sourceName:A.sourceName,displayName:B.displayName===C.get(G)?.displayName?A.displayName:B.displayName};return hm(A,P)?A:P}),N=g.autoplayClip===x.autoplayClip?v.autoplayClip:[...u].find(([,A])=>A===g.autoplayClip)?.[0]??null;return N===v.autoplayClip&&m.every((A,G)=>A===v.clips[G])?v:{clips:m,autoplayClip:N}};e&&i(T=>{let f=y(e,T);return f===T.animations?T:{...T,animations:f}}),n(T=>T.map(f=>ac(f,t,y(f.url,Xe(t,f.modelSettings)),!0))),s()}}}import{useEffect as xm,useRef as vm,useState as ir}from"react";import{ChevronLeft as ym,ChevronRight as wm,FileUp as Sm,RotateCcw as km,X as Cm}from"lucide-react";import{Fragment as Nm,jsx as V,jsxs as De}from"react/jsx-runtime";var Mm="image/png,image/jpeg,image/webp,image/avif,image/gif";function Pm(e){let t=e.trim();return!!(t&&$t(t))||/^(blob:|data:image\/)/i.test(t)}var Bm=["lit","unlit","normals"],Tm=["default","color","image","environment"],Rm={pbr:"PBR",matcap:"Matcap","uv-checker":"UV checker"};function lc(e){let t=e%360;return t<0?t+360:t}function dc({config:e,onChange:t,diagnostics:i,onDiagnosticsOpenChange:a,materialVariantGroups:o=[]}){let{model:n,wireframe:d}=e,s=Ul(n),p=o.length>0?s.filter(u=>!o.some(v=>v.variants.some(m=>m.name===u))):[],{tier:c}=it(),x=id(),[h,g]=ir({orientation:!0,diagnostics:!1,autoRotate:!1,wireframe:!1,section:!1});xm(()=>(a?.(h.diagnostics),()=>a?.(!1)),[h.diagnostics,a]);let C=u=>g(v=>({...v,[u]:!v[u]})),M=u=>t({...e,model:u}),y=u=>t({...e,wireframe:u}),T=e.section??zl,f=u=>t({...e,section:{...T,...u}});return De("div",{className:"se-generalContent",children:[De(oe,{title:"Display",open:h.orientation,onToggle:()=>C("orientation"),children:[De("div",{className:"se-field se-fieldInline",children:[De("div",{className:"se-fieldLabel se-fieldLabel--action",children:[V("span",{children:"Straighten"}),V("button",{type:"button",className:"se-iconButton",onClick:()=>M({...n,rotation:[0,0,0]}),"aria-label":"Reset model rotation",children:V(km,{size:12})})]}),V("div",{className:"se-axisStepperGrid",children:["X","Y","Z"].map((u,v)=>De("div",{className:"se-axisStepper",children:[V("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let m=[...n.rotation];m[v]=lc(m[v]-90),M({...n,rotation:m})},"aria-label":`Rotate ${u} axis backward`,children:V(ym,{size:12})}),V("span",{className:"se-axisStepperLabel",children:u}),V("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let m=[...n.rotation];m[v]=lc(m[v]+90),M({...n,rotation:m})},"aria-label":`Rotate ${u} axis forward`,children:V(wm,{size:12})})]},u))})]}),V(kt,{label:"Rotation",path:"sceneConfig.model.rotation",value:n.rotation,min:0,max:360,step:1,onChange:u=>M({...n,rotation:u})}),De("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.model.renderer",children:[V("span",{className:"se-fieldLabel",children:"Renderer"}),V("div",{className:"se-segmentedControl se-segmentedControl--renderer",children:Ol.map(u=>V("button",{type:"button",className:`se-segmentedOption ${n.renderer===u?"se-segmentedOption--active":""}`,onClick:()=>M({...n,renderer:u}),children:Rm[u]},u))})]}),V(st,{label:"Shading",path:"sceneConfig.model.shading",value:n.shading,options:Bm,onChange:u=>M({...n,shading:u})}),o.length>0&&!nt(c,"materialVariants")?V(We,{requiredTier:"starter",feature:"Material variants"}):null,(nt(c,"materialVariants")?o:[]).map((u,v)=>{let m=s.find(N=>u.variants.some(A=>A.name===N));return De("label",{className:"se-field se-fieldInline",children:[V("span",{className:"se-fieldLabel",children:u.name??"Material variant"}),De("select",{className:"se-select",value:m??"",onChange:N=>{let A=N.target.value,G=s.filter(B=>B!==m);M(aa(n,A?$l(G,A,o):G))},children:[V("option",{value:"",children:"Model default"}),u.variants.map(N=>V("option",{value:N.name,children:N.label},N.name))]})]},u.name??`group-${v}`)}),p.length>0?De("div",{className:"se-placeholder se-placeholder--spaced",children:["Not in this model: ",p.join(", "),"."," ",V("button",{type:"button",className:"se-linkButton",onClick:()=>M(aa(n,s.filter(u=>!p.includes(u)))),children:"Remove"})]}):null]}),De(oe,{title:"Auto rotate",open:h.autoRotate,onToggle:()=>C("autoRotate"),trailing:V(se,{checked:n.autoRotate??!1,onChange:u=>M({...n,autoRotate:u}),label:"Toggle auto rotate"}),children:[n.autoRotate&&x?V("div",{className:"se-placeholder se-placeholder--spaced",children:"Your device is set to reduce motion, so this preview won't turn. Visitors without that setting will see it."}):null,n.autoRotate?V(O,{label:"Speed",path:"sceneConfig.model.autoRotateSpeed",value:n.autoRotateSpeed??1,min:.1,max:3,step:.1,formatValue:u=>`${u.toFixed(1)}x`,onChange:u=>M({...n,autoRotateSpeed:u})}):V("div",{className:"se-placeholder",children:"Enable auto rotate to adjust its speed."})]}),V(oe,{title:"Wireframe",open:h.wireframe,onToggle:()=>C("wireframe"),disabled:!d.enabled,trailing:V(se,{checked:d.enabled,onChange:u=>y({...d,enabled:u}),label:"Toggle wireframe preview"}),children:De(Nm,{children:[V(O,{label:"Opacity",path:"sceneConfig.wireframe.opacity",value:d.opacity,min:0,max:1,step:.01,onChange:u=>y({...d,opacity:u})}),V(pt,{label:"Wire color",path:"sceneConfig.wireframe.color",value:d.color,onChange:u=>y({...d,color:u})})]})}),V(oe,{title:"Section cut",open:h.section,onToggle:()=>C("section"),disabled:!T.enabled,trailing:V(se,{checked:T.enabled,onChange:u=>{f({enabled:u}),u&&g(v=>({...v,section:!0}))},label:"Toggle section cut"}),children:V("div",{"data-ri-path":"sceneConfig.section",children:V(ud,{section:T,onChange:f})})}),i&&V(oe,{title:"Diagnostics",open:h.diagnostics,onToggle:()=>C("diagnostics"),children:V(Md,{...i})})]})}function cc({config:e,onChange:t}){let{camera:i}=e,[a,o]=ir(!0);return V("div",{className:"se-generalContent",children:V(oe,{title:"Lens",open:a,onToggle:()=>o(n=>!n),children:V(O,{label:"Field of view",path:"sceneConfig.camera.fieldOfView",value:i.fieldOfView,min:20,max:100,step:.1,formatValue:n=>`${n.toFixed(1)}\xB0`,onChange:n=>t({...e,camera:{...i,fieldOfView:n}})})})})}function pc({config:e,onChange:t,onImageFile:i}){let{background:a,environment:o,groundShadows:n}=e,d=vm(null),[s,p]=ir(null),c=Pm(a.imageUrl),{tier:x}=it(),[h,g]=ir({environment:!0,envShadow:!1,background:!0,groundShadows:!1}),C=u=>g(v=>({...v,[u]:!v[u]})),M=u=>t({...e,background:u}),y=u=>t({...e,environment:u}),T=u=>t({...e,groundShadows:u}),f=u=>{if(!u.type.startsWith("image/")){p("Choose a PNG, JPG, WEBP, AVIF or GIF image.");return}p(null);let v=gn(u);v===a.imageUrl&&$t(v)||It(v,URL.createObjectURL(u)),i?.(v,u),M({...a,imageUrl:v})};return De("div",{className:"se-generalContent",children:[De(oe,{title:"Environment",open:h.environment,onToggle:()=>C("environment"),children:[De("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.environment.source",children:[V("span",{className:"se-fieldLabel",children:"Source"}),V("div",{className:"se-segmentedControl",children:["preset","custom"].map(u=>V("button",{type:"button",className:`se-segmentedOption ${o.source===u?"se-segmentedOption--active":""}`,onClick:()=>y({...o,source:u}),children:u==="preset"?"Preset":"Custom"},u))})]}),o.source==="preset"?V(st,{label:"Preset",path:"sceneConfig.environment.preset",value:o.preset,options:El,onChange:u=>y({...o,source:"preset",preset:u})}):nt(x,"customEnvironment")?De("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.environment.customEnvironmentUrl",children:[V("span",{className:"se-fieldLabel",children:"URL"}),V("input",{type:"text",className:"se-textInput","aria-label":"Custom environment URL",placeholder:"https://example.com/studio.hdr",value:o.customEnvironmentUrl,onChange:u=>y({...o,customEnvironmentUrl:u.target.value})}),o.customEnvironmentUrl.trim()&&!Nl(o.customEnvironmentUrl)?V("span",{className:"bb-note bb-note--error se-fieldFull",children:"Use an HDR, EXR, JPG, PNG, or WEBP URL."}):null]}):V(We,{requiredTier:"starter",feature:"Custom environments"}),V(O,{label:"Intensity",path:"sceneConfig.environment.intensity",value:o.intensity,min:0,max:3,step:.05,onChange:u=>y({...o,intensity:u})}),V(O,{label:"Rotation",path:"sceneConfig.environment.rotation",value:o.rotation,min:0,max:360,step:1,formatValue:u=>`${u}\xB0`,onChange:u=>y({...o,rotation:u})}),V(be,{label:"As background",path:"sceneConfig.background.type",checked:a.enabled&&a.type==="environment",onChange:u=>M(u?{...a,enabled:!0,type:"environment"}:{...a,type:"color"})}),V("p",{className:"bb-note se-fieldFull",children:"It always lights the model; this also draws it behind."})]}),De(oe,{title:"Environment shadow",open:h.envShadow,onToggle:()=>C("envShadow"),disabled:!o.shadowLight.enabled,trailing:V(se,{checked:o.shadowLight.enabled,onChange:u=>y({...o,shadowLight:{...o.shadowLight,enabled:u}}),label:"Toggle environment shadow light"}),children:[V(O,{label:"Light intensity",path:"sceneConfig.environment.shadowLight.intensity",value:o.shadowLight.intensity,min:0,max:20,step:.1,onChange:u=>y({...o,shadowLight:{...o.shadowLight,intensity:u}})}),V(O,{label:"Shadow bias",path:"sceneConfig.environment.shadowLight.bias",value:o.shadowLight.bias,min:-.01,max:.01,step:1e-4,onChange:u=>y({...o,shadowLight:{...o.shadowLight,bias:u}})})]}),De(oe,{title:"Background",open:h.background,onToggle:()=>C("background"),children:[V(st,{label:"Show",path:"sceneConfig.background.type",value:a.enabled?a.type:"default",options:Tm,onChange:u=>M(u==="default"?{...a,enabled:!1}:{...a,enabled:!0,type:u})}),a.enabled?a.type==="image"&&!nt(x,"backgroundImages")?V(We,{requiredTier:"starter",feature:"Background images"}):a.type==="image"?De("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.background.imageUrl",children:[V("label",{className:"se-fieldLabel",htmlFor:"se-background-image-url",children:"Image"}),De("div",{className:"bb-fileField",children:[V("input",{id:"se-background-image-url",type:"text",className:"bb-input bb-fileField-input",placeholder:"Paste a link or upload",value:a.imageUrl,readOnly:c,onChange:u=>{p(null),M({...a,imageUrl:u.target.value})}}),c?V("button",{type:"button",className:"bb-fileFieldButton",onClick:()=>M({...a,imageUrl:""}),"aria-label":"Remove uploaded background image",title:"Remove uploaded image",children:V(Cm,{size:13})}):V("button",{type:"button",className:"bb-fileFieldButton",onClick:()=>d.current?.click(),"aria-label":"Upload background image",title:"Upload image",children:V(Sm,{size:13})}),V("input",{ref:d,type:"file",accept:Mm,className:"bb-hiddenInput",onChange:u=>{let v=u.target.files?.[0];u.target.value="",v&&f(v)}})]}),s?V("span",{className:"bb-note bb-note--error se-fieldFull",children:s}):c?V("span",{className:"bb-note se-fieldFull",children:"Uploaded files are bundled into the scene export."}):null]}):null:null,a.enabled&&a.type==="color"?V(pt,{label:"Color",path:"sceneConfig.background.color",value:a.color,onChange:u=>M({...a,color:u})}):null]}),De(oe,{title:"Ground shadows",open:h.groundShadows,onToggle:()=>C("groundShadows"),disabled:!n.enabled,trailing:V(se,{checked:n.enabled,onChange:u=>T({...n,enabled:u}),label:"Toggle ground shadows"}),children:[V(O,{label:"Intensity",path:"sceneConfig.groundShadows.intensity",value:n.intensity,min:0,max:1,step:.01,onChange:u=>T({...n,intensity:u})}),V(O,{label:"Border fade",path:"sceneConfig.groundShadows.borderFade",value:n.borderFade,min:0,max:10,step:.1,onChange:u=>T({...n,borderFade:u})}),V(O,{label:"Height",path:"sceneConfig.groundShadows.height",value:n.height,min:-5,max:5,step:.1,onChange:u=>T({...n,height:u})}),V(O,{label:"Size",path:"sceneConfig.groundShadows.size",value:n.size,min:1,max:50,step:.5,onChange:u=>T({...n,size:u})})]})]})}import{useEffect as Om,useRef as Em,useState as rr}from"react";import{Lock as jm,Plus as Im}from"lucide-react";import{jsx as ce,jsxs as Cn}from"react/jsx-runtime";var Am=["linear","reinhard","aces"];function uc({pp:e,set:t,open:i,toggle:a}){let{colorAverage:o}=e;return ce(oe,{title:"Color average",tooltip:"Blends the frame toward a single average color for a washed-out stylized look.",open:i.colorAverage,onToggle:()=>a("colorAverage"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("colorAverage",{...o,enabled:n}),label:"Toggle color average"}),children:ce("div",{className:"se-placeholder",children:"Averages the frame color using the docs default blend mode."})})}function bc({pp:e,set:t,open:i,toggle:a}){let{brightnessContrast:o}=e;return Cn(oe,{title:"Brightness and contrast",tooltip:"Raises or lowers overall brightness and contrast across the scene.",open:i.brightnessContrast,onToggle:()=>a("brightnessContrast"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("brightnessContrast",{...o,enabled:n}),label:"Toggle brightness contrast"}),children:[ce(O,{path:"sceneConfig.postProcessing.brightnessContrast.brightness",label:"Brightness",value:o.brightness,min:-1,max:1,step:.01,onChange:n=>t("brightnessContrast",{...o,brightness:n})}),ce(O,{path:"sceneConfig.postProcessing.brightnessContrast.contrast",label:"Contrast",value:o.contrast,min:-1,max:1,step:.01,onChange:n=>t("brightnessContrast",{...o,contrast:n})})]})}function gc({pp:e,set:t,open:i,toggle:a}){let{hueSaturation:o}=e;return Cn(oe,{title:"Hue and saturation",tooltip:"Shifts the hue and saturation to tint the whole image.",open:i.hueSaturation,onToggle:()=>a("hueSaturation"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("hueSaturation",{...o,enabled:n}),label:"Toggle hue saturation"}),children:[ce(O,{path:"sceneConfig.postProcessing.hueSaturation.hue",label:"Hue",value:o.hue,min:-Math.PI,max:Math.PI,step:.01,formatValue:n=>`${n.toFixed(2)} rad`,onChange:n=>t("hueSaturation",{...o,hue:n})}),ce(O,{path:"sceneConfig.postProcessing.hueSaturation.saturation",label:"Saturation",value:o.saturation,min:-1,max:1,step:.01,onChange:n=>t("hueSaturation",{...o,saturation:n})})]})}function mc({pp:e,set:t,open:i,toggle:a}){let{vignette:o}=e;return Cn(oe,{title:"Vignette",tooltip:"Darkens the edges of the screen so the center feels more focused.",open:i.vignette,onToggle:()=>a("vignette"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("vignette",{...o,enabled:n}),label:"Toggle vignette"}),children:[ce(O,{path:"sceneConfig.postProcessing.vignette.offset",label:"Offset",value:o.offset,min:0,max:1,step:.01,onChange:n=>t("vignette",{...o,offset:n})}),ce(O,{path:"sceneConfig.postProcessing.vignette.darkness",label:"Darkness",value:o.darkness,min:0,max:1,step:.01,onChange:n=>t("vignette",{...o,darkness:n})}),ce(be,{path:"sceneConfig.postProcessing.vignette.eskil",label:"Eskil",checked:o.eskil,onChange:n=>t("vignette",{...o,eskil:n})})]})}function fc({pp:e,set:t,open:i,toggle:a}){let{bloom:o}=e;return Cn(oe,{title:"Bloom",tooltip:"Makes bright areas glow and bleed softly into nearby pixels.",open:i.bloom,onToggle:()=>a("bloom"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("bloom",{...o,enabled:n}),label:"Toggle bloom"}),children:[ce(O,{path:"sceneConfig.postProcessing.bloom.luminanceThreshold",label:"Threshold",value:o.luminanceThreshold,min:0,max:1,step:.01,onChange:n=>t("bloom",{...o,luminanceThreshold:n})}),ce(O,{path:"sceneConfig.postProcessing.bloom.luminanceSmoothing",label:"Smoothing",value:o.luminanceSmoothing,min:0,max:1,step:.01,onChange:n=>t("bloom",{...o,luminanceSmoothing:n})}),ce(O,{path:"sceneConfig.postProcessing.bloom.intensity",label:"Intensity",value:o.intensity,min:0,max:3,step:.05,onChange:n=>t("bloom",{...o,intensity:n})}),ce(be,{path:"sceneConfig.postProcessing.bloom.mipmapBlur",label:"Mipmap blur",checked:o.mipmapBlur,onChange:n=>t("bloom",{...o,mipmapBlur:n})}),ce(O,{path:"sceneConfig.postProcessing.bloom.radius",label:"Radius",value:o.radius,min:0,max:1,step:.01,onChange:n=>t("bloom",{...o,radius:n})}),ce(O,{path:"sceneConfig.postProcessing.bloom.levels",label:"Levels",value:o.levels,min:1,max:16,step:1,onChange:n=>t("bloom",{...o,levels:n})})]})}function hc({pp:e,set:t,open:i,toggle:a}){let{toneMapping:o}=e;return Cn(oe,{title:"Tone mapping",tooltip:"Remaps HDR lighting to screen output and controls exposure style.",open:i.toneMapping,onToggle:()=>a("toneMapping"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("toneMapping",{...o,enabled:n}),label:"Toggle tone mapping"}),children:[Cn("div",{className:"se-field",children:[ce("span",{className:"se-fieldLabel",children:"Mode"}),ce("div",{className:"se-segmentedControl",children:Am.map(n=>ce("button",{type:"button",className:`se-segmentedOption ${o.mode===n?"se-segmentedOption--active":""}`,onClick:()=>t("toneMapping",{...o,mode:n}),children:n==="aces"?"Filmic":n.charAt(0).toUpperCase()+n.slice(1)},n))})]}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.resolution",label:"Resolution",value:o.resolution,min:64,max:4096,step:64,onChange:n=>t("toneMapping",{...o,resolution:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.whitePoint",label:"White point",value:o.whitePoint,min:0,max:16,step:.01,onChange:n=>t("toneMapping",{...o,whitePoint:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.middleGrey",label:"Middle grey",value:o.middleGrey,min:0,max:1,step:.01,onChange:n=>t("toneMapping",{...o,middleGrey:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.minLuminance",label:"Min luminance",value:o.minLuminance,min:0,max:1,step:.01,onChange:n=>t("toneMapping",{...o,minLuminance:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.averageLuminance",label:"Average luminance",value:o.averageLuminance,min:0,max:4,step:.01,onChange:n=>t("toneMapping",{...o,averageLuminance:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.adaptationRate",label:"Adaptation rate",value:o.adaptationRate,min:0,max:10,step:.01,onChange:n=>t("toneMapping",{...o,adaptationRate:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.exposure",label:"Exposure",value:o.exposure,min:0,max:3,step:.01,onChange:n=>t("toneMapping",{...o,exposure:n})})]})}function xc({pp:e,set:t,open:i,toggle:a}){let{sepia:o}=e;return ce(oe,{title:"Sepia",tooltip:"Adds a warm vintage brown tint to the entire image.",open:i.sepia,onToggle:()=>a("sepia"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("sepia",{...o,enabled:n}),label:"Toggle sepia"}),children:ce(O,{path:"sceneConfig.postProcessing.sepia.intensity",label:"Intensity",value:o.intensity,min:0,max:1,step:.01,onChange:n=>t("sepia",{...o,intensity:n})})})}import{jsx as Y,jsxs as oi}from"react/jsx-runtime";function vc({pp:e,set:t,open:i,toggle:a}){let{ssao:o}=e;return oi(oe,{title:"Ambient occlusion",tooltip:"Adds soft contact shadows in corners, creases, and tight spaces.",open:i.ssao,onToggle:()=>a("ssao"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("ssao",{...o,enabled:n}),label:"Toggle ssao"}),children:[Y(O,{path:"sceneConfig.postProcessing.ssao.samples",label:"Samples",value:o.samples,min:1,max:64,step:1,onChange:n=>t("ssao",{...o,samples:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.rings",label:"Rings",value:o.rings,min:1,max:12,step:1,onChange:n=>t("ssao",{...o,rings:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.intensity",label:"Intensity",value:o.intensity,min:0,max:20,step:.5,onChange:n=>t("ssao",{...o,intensity:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.radius",label:"Radius",value:o.radius,min:.01,max:1,step:.01,onChange:n=>t("ssao",{...o,radius:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.bias",label:"Bias",value:o.bias,min:0,max:.1,step:.001,onChange:n=>t("ssao",{...o,bias:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.luminanceInfluence",label:"Luminance influence",value:o.luminanceInfluence,min:0,max:1,step:.01,onChange:n=>t("ssao",{...o,luminanceInfluence:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.fade",label:"Fade",value:o.fade,min:0,max:.1,step:.001,onChange:n=>t("ssao",{...o,fade:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.minRadiusScale",label:"Min radius scale",value:o.minRadiusScale,min:0,max:1,step:.01,onChange:n=>t("ssao",{...o,minRadiusScale:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.worldDistanceThreshold",label:"World distance threshold",value:o.worldDistanceThreshold,min:0,max:100,step:.1,onChange:n=>t("ssao",{...o,worldDistanceThreshold:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.worldDistanceFalloff",label:"World distance falloff",value:o.worldDistanceFalloff,min:0,max:20,step:.1,onChange:n=>t("ssao",{...o,worldDistanceFalloff:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.worldProximityThreshold",label:"World proximity threshold",value:o.worldProximityThreshold,min:0,max:100,step:.1,onChange:n=>t("ssao",{...o,worldProximityThreshold:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.worldProximityFalloff",label:"World proximity falloff",value:o.worldProximityFalloff,min:0,max:20,step:.1,onChange:n=>t("ssao",{...o,worldProximityFalloff:n})})]})}function yc({pp:e,set:t,open:i,toggle:a}){let{autofocus:o}=e;return oi(oe,{title:"Auto focus",tooltip:"Keeps the focus plane tracking a subject so the image stays sharp where you want it.",open:i.autofocus,onToggle:()=>a("autofocus"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("autofocus",{...o,enabled:n}),label:"Toggle autofocus"}),children:[Y(O,{path:"sceneConfig.postProcessing.autofocus.focusDistance",label:"Focus distance",value:o.focusDistance,min:0,max:50,step:.1,onChange:n=>t("autofocus",{...o,focusDistance:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.focusRange",label:"Focus range",value:o.focusRange,min:.1,max:50,step:.1,onChange:n=>t("autofocus",{...o,focusRange:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.focalLength",label:"Focal length",value:o.focalLength,min:0,max:1,step:.01,onChange:n=>t("autofocus",{...o,focalLength:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.bokehScale",label:"Bokeh scale",value:o.bokehScale,min:0,max:20,step:.1,onChange:n=>t("autofocus",{...o,bokehScale:n})}),Y(kt,{path:"sceneConfig.postProcessing.autofocus.target",label:"Target",value:o.target,min:-100,max:100,step:.1,onChange:n=>t("autofocus",{...o,target:n})}),Y(be,{path:"sceneConfig.postProcessing.autofocus.mouse",label:"Mouse follow",checked:o.mouse,onChange:n=>t("autofocus",{...o,mouse:n})}),Y(be,{path:"sceneConfig.postProcessing.autofocus.manual",label:"Manual update",checked:o.manual,onChange:n=>t("autofocus",{...o,manual:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.debug",label:"Debug",value:o.debug,min:0,max:1,step:.01,onChange:n=>t("autofocus",{...o,debug:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.smoothTime",label:"Smooth time",value:o.smoothTime,min:0,max:2,step:.01,onChange:n=>t("autofocus",{...o,smoothTime:n})})]})}function wc({pp:e,set:t,open:i,toggle:a}){let{godRays:o}=e;return oi(oe,{title:"God rays",tooltip:"Creates light shafts that streak outward from a bright sun or light source.",open:i.godRays,onToggle:()=>a("godRays"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("godRays",{...o,enabled:n}),label:"Toggle god rays"}),children:[Y(kt,{path:"sceneConfig.postProcessing.godRays.sunPosition",label:"Sun position",value:o.sunPosition,min:-100,max:100,step:.1,onChange:n=>t("godRays",{...o,sunPosition:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.samples",label:"Samples",value:o.samples,min:1,max:128,step:1,onChange:n=>t("godRays",{...o,samples:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.density",label:"Density",value:o.density,min:0,max:2,step:.01,onChange:n=>t("godRays",{...o,density:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.decay",label:"Decay",value:o.decay,min:0,max:1,step:.01,onChange:n=>t("godRays",{...o,decay:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.weight",label:"Weight",value:o.weight,min:0,max:2,step:.01,onChange:n=>t("godRays",{...o,weight:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.exposure",label:"Exposure",value:o.exposure,min:0,max:2,step:.01,onChange:n=>t("godRays",{...o,exposure:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.clampMax",label:"Clamp max",value:o.clampMax,min:0,max:2,step:.01,onChange:n=>t("godRays",{...o,clampMax:n})}),Y(be,{path:"sceneConfig.postProcessing.godRays.blur",label:"Blur",checked:o.blur,onChange:n=>t("godRays",{...o,blur:n})}),Y(st,{path:"sceneConfig.postProcessing.godRays.kernelSize",label:"Kernel size",value:o.kernelSize,options:Wn,onChange:n=>t("godRays",{...o,kernelSize:n})})]})}function Sc({pp:e,set:t,open:i,toggle:a}){let{lensflare:o}=e;return oi(oe,{title:"Lens flare",tooltip:"Adds camera flare artifacts and glow from a bright light source.",open:i.lensflare,onToggle:()=>a("lensflare"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("lensflare",{...o,enabled:n}),label:"Toggle lensflare"}),children:[Y(kt,{path:"sceneConfig.postProcessing.lensflare.lensPosition",label:"Lens position",value:o.lensPosition,min:-100,max:100,step:.1,onChange:n=>t("lensflare",{...o,lensPosition:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.smoothTime",label:"Smooth time",value:o.smoothTime,min:0,max:1,step:.01,onChange:n=>t("lensflare",{...o,smoothTime:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.glareSize",label:"Glare size",value:o.glareSize,min:0,max:1,step:.01,onChange:n=>t("lensflare",{...o,glareSize:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.flareSize",label:"Flare size",value:o.flareSize,min:0,max:.1,step:.001,onChange:n=>t("lensflare",{...o,flareSize:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.flareSpeed",label:"Flare speed",value:o.flareSpeed,min:0,max:.2,step:.001,onChange:n=>t("lensflare",{...o,flareSpeed:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.flareShape",label:"Flare shape",value:o.flareShape,min:0,max:.2,step:.001,onChange:n=>t("lensflare",{...o,flareShape:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.animated",label:"Animated",checked:o.animated,onChange:n=>t("lensflare",{...o,animated:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.anamorphic",label:"Anamorphic",checked:o.anamorphic,onChange:n=>t("lensflare",{...o,anamorphic:n})}),Y(pt,{path:"sceneConfig.postProcessing.lensflare.colorGain",label:"Color gain",value:o.colorGain,onChange:n=>t("lensflare",{...o,colorGain:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.haloScale",label:"Halo scale",value:o.haloScale,min:0,max:2,step:.01,onChange:n=>t("lensflare",{...o,haloScale:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.secondaryGhosts",label:"Secondary ghosts",checked:o.secondaryGhosts,onChange:n=>t("lensflare",{...o,secondaryGhosts:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.aditionalStreaks",label:"Additional streaks",checked:o.aditionalStreaks,onChange:n=>t("lensflare",{...o,aditionalStreaks:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.ghostScale",label:"Ghost scale",value:o.ghostScale,min:0,max:1,step:.01,onChange:n=>t("lensflare",{...o,ghostScale:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.opacity",label:"Opacity",value:o.opacity,min:0,max:1,step:.01,onChange:n=>t("lensflare",{...o,opacity:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.starBurst",label:"Star burst",checked:o.starBurst,onChange:n=>t("lensflare",{...o,starBurst:n})})]})}function kc({pp:e,set:t,open:i,toggle:a}){let{depthOfField:o}=e;return oi(oe,{title:"Depth of field",tooltip:"Blurs areas that sit away from the focal plane for a camera-like look.",open:i.depthOfField,onToggle:()=>a("depthOfField"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("depthOfField",{...o,enabled:n}),label:"Toggle depth of field"}),children:[Y(O,{path:"sceneConfig.postProcessing.depthOfField.focusDistance",label:"Focus distance",value:o.focusDistance,min:0,max:50,step:.1,onChange:n=>t("depthOfField",{...o,focusDistance:n})}),Y(O,{path:"sceneConfig.postProcessing.depthOfField.focusRange",label:"Focus range",value:o.focusRange,min:.1,max:50,step:.1,onChange:n=>t("depthOfField",{...o,focusRange:n})}),Y(O,{path:"sceneConfig.postProcessing.depthOfField.focalLength",label:"Focal length",value:o.focalLength,min:0,max:1,step:.01,onChange:n=>t("depthOfField",{...o,focalLength:n})}),Y(O,{path:"sceneConfig.postProcessing.depthOfField.bokehScale",label:"Bokeh scale",value:o.bokehScale,min:0,max:20,step:.1,onChange:n=>t("depthOfField",{...o,bokehScale:n})})]})}import{jsx as re,jsxs as Mn}from"react/jsx-runtime";function Cc({pp:e,set:t,open:i,toggle:a}){let{dotScreen:o}=e;return Mn(oe,{title:"Dot screen",tooltip:"Overlays a halftone dot pattern for a printed or retro look.",open:i.dotScreen,onToggle:()=>a("dotScreen"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("dotScreen",{...o,enabled:n}),label:"Toggle dot screen"}),children:[re(O,{path:"sceneConfig.postProcessing.dotScreen.angle",label:"Angle",value:o.angle,min:0,max:Math.PI*2,step:.01,formatValue:n=>`${n.toFixed(2)} rad`,onChange:n=>t("dotScreen",{...o,angle:n})}),re(O,{path:"sceneConfig.postProcessing.dotScreen.scale",label:"Scale",value:o.scale,min:.1,max:10,step:.05,onChange:n=>t("dotScreen",{...o,scale:n})})]})}function Mc({pp:e,set:t,open:i,toggle:a}){let{glitch:o}=e;return Mn(oe,{title:"Glitch",tooltip:"Introduces digital distortion, tearing, and scan noise.",open:i.glitch,onToggle:()=>a("glitch"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("glitch",{...o,enabled:n}),label:"Toggle glitch"}),children:[re(st,{path:"sceneConfig.postProcessing.glitch.mode",label:"Mode",value:o.mode,options:jl,onChange:n=>t("glitch",{...o,mode:n})}),re($o,{path:"sceneConfig.postProcessing.glitch.delay",label:"Delay",value:o.delay,min:0,max:10,step:.01,onChange:n=>t("glitch",{...o,delay:n})}),re($o,{path:"sceneConfig.postProcessing.glitch.duration",label:"Duration",value:o.duration,min:0,max:5,step:.01,onChange:n=>t("glitch",{...o,duration:n})}),re($o,{path:"sceneConfig.postProcessing.glitch.strength",label:"Strength",value:o.strength,min:0,max:2,step:.01,onChange:n=>t("glitch",{...o,strength:n})}),re($o,{path:"sceneConfig.postProcessing.glitch.chromaticAberrationOffset",label:"Chromatic aberration offset",value:o.chromaticAberrationOffset,min:0,max:.02,step:1e-4,onChange:n=>t("glitch",{...o,chromaticAberrationOffset:n})}),re(O,{path:"sceneConfig.postProcessing.glitch.columns",label:"Columns",value:o.columns,min:0,max:.5,step:.001,onChange:n=>t("glitch",{...o,columns:n})}),re(O,{path:"sceneConfig.postProcessing.glitch.ratio",label:"Ratio",value:o.ratio,min:0,max:1,step:.01,onChange:n=>t("glitch",{...o,ratio:n})})]})}function Pc({pp:e,set:t,open:i,toggle:a}){let{grid:o}=e;return Mn(oe,{title:"Grid",tooltip:"Adds a visual grid overlay that feels retro or debug-like.",open:i.grid,onToggle:()=>a("grid"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("grid",{...o,enabled:n}),label:"Toggle grid"}),children:[re(O,{path:"sceneConfig.postProcessing.grid.scale",label:"Scale",value:o.scale,min:.1,max:10,step:.05,onChange:n=>t("grid",{...o,scale:n})}),re(O,{path:"sceneConfig.postProcessing.grid.lineWidth",label:"Line width",value:o.lineWidth,min:0,max:1,step:.01,onChange:n=>t("grid",{...o,lineWidth:n})})]})}function Bc({pp:e,set:t,open:i,toggle:a}){let{chromaticAberration:o}=e;return Mn(oe,{title:"Chromatic aberration",tooltip:"Separates color channels slightly to mimic lens fringing.",open:i.chromaticAberration,onToggle:()=>a("chromaticAberration"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("chromaticAberration",{...o,enabled:n}),label:"Toggle chromatic aberration"}),children:[re(O,{path:"sceneConfig.postProcessing.chromaticAberration.offsetX",label:"Offset X",value:o.offsetX,min:0,max:.02,step:1e-4,onChange:n=>t("chromaticAberration",{...o,offsetX:n})}),re(O,{path:"sceneConfig.postProcessing.chromaticAberration.offsetY",label:"Offset Y",value:o.offsetY,min:0,max:.02,step:1e-4,onChange:n=>t("chromaticAberration",{...o,offsetY:n})}),re(be,{path:"sceneConfig.postProcessing.chromaticAberration.radialModulation",label:"Radial modulation",checked:o.radialModulation,onChange:n=>t("chromaticAberration",{...o,radialModulation:n})}),re(O,{path:"sceneConfig.postProcessing.chromaticAberration.modulationOffset",label:"Modulation offset",value:o.modulationOffset,min:0,max:1,step:.01,onChange:n=>t("chromaticAberration",{...o,modulationOffset:n})})]})}function Tc({pp:e,set:t,open:i,toggle:a}){let{noise:o}=e;return Mn(oe,{title:"Noise",tooltip:"Adds film grain or static noise to the rendered image.",open:i.noise,onToggle:()=>a("noise"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("noise",{...o,enabled:n}),label:"Toggle noise"}),children:[re(O,{path:"sceneConfig.postProcessing.noise.opacity",label:"Amount",value:o.opacity,min:0,max:1,step:.01,onChange:n=>t("noise",{...o,opacity:n})}),re(be,{path:"sceneConfig.postProcessing.noise.premultiply",label:"Premultiply",checked:o.premultiply,onChange:n=>t("noise",{...o,premultiply:n})})]})}function Rc({pp:e,set:t,open:i,toggle:a}){let{scanline:o}=e;return re(oe,{title:"Scan lines",tooltip:"Draws horizontal CRT-style scan lines over the frame.",open:i.scanline,onToggle:()=>a("scanline"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("scanline",{...o,enabled:n}),label:"Toggle scanline"}),children:re(O,{path:"sceneConfig.postProcessing.scanline.density",label:"Density",value:o.density,min:0,max:10,step:.25,onChange:n=>t("scanline",{...o,density:n})})})}function Nc({pp:e,set:t,open:i,toggle:a}){let{pixelation:o}=e;return re(oe,{title:"Pixelation",tooltip:"Reduces detail into larger pixels for a blocky stylized effect.",open:i.pixelation,onToggle:()=>a("pixelation"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("pixelation",{...o,enabled:n}),label:"Toggle pixelation"}),children:re(O,{path:"sceneConfig.postProcessing.pixelation.granularity",label:"Granularity",value:o.granularity,min:0,max:20,step:1,onChange:n=>t("pixelation",{...o,granularity:n})})})}function Ac({pp:e,set:t,open:i,toggle:a}){let{ramp:o}=e;return Mn(oe,{title:"Color ramp",tooltip:"Adds a screen-space color gradient, or masks effects earlier in the stack.",open:i.ramp,onToggle:()=>a("ramp"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("ramp",{...o,enabled:n}),label:"Toggle ramp"}),children:[re(st,{path:"sceneConfig.postProcessing.ramp.rampType",label:"Ramp type",value:o.rampType,options:Il,onChange:n=>t("ramp",{...o,rampType:n})}),re($o,{path:"sceneConfig.postProcessing.ramp.rampStart",label:"Ramp start",value:o.rampStart,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,rampStart:n})}),re($o,{path:"sceneConfig.postProcessing.ramp.rampEnd",label:"Ramp end",value:o.rampEnd,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,rampEnd:n})}),re(pt,{path:"sceneConfig.postProcessing.ramp.startColor",label:"Start color",value:o.startColor,onChange:n=>t("ramp",{...o,startColor:n})}),re(pt,{path:"sceneConfig.postProcessing.ramp.endColor",label:"End color",value:o.endColor,onChange:n=>t("ramp",{...o,endColor:n})}),!o.rampMask&&re(O,{path:"sceneConfig.postProcessing.ramp.opacity",label:"Gradient opacity",value:o.opacity??.5,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,opacity:n})}),re(O,{path:"sceneConfig.postProcessing.ramp.rampBias",label:"Bias",value:o.rampBias,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,rampBias:n})}),re(O,{path:"sceneConfig.postProcessing.ramp.rampGain",label:"Gain",value:o.rampGain,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,rampGain:n})}),re(be,{path:"sceneConfig.postProcessing.ramp.rampMask",label:"Mask earlier effects",checked:o.rampMask,onChange:n=>t("ramp",{...o,rampMask:n})}),re(be,{path:"sceneConfig.postProcessing.ramp.rampInvert",label:"Invert",checked:o.rampInvert,onChange:n=>t("ramp",{...o,rampInvert:n})})]})}import{jsx as Te,jsxs as Ic}from"react/jsx-runtime";function Oc({pp:e,set:t,open:i,toggle:a}){let{outline:o}=e;return Ic(oe,{title:"Outline",tooltip:"Draws a visible edge around the selected object binding.",open:i.outline,onToggle:()=>a("outline"),disabled:!o.enabled,trailing:Te(se,{checked:o.enabled,onChange:n=>t("outline",{...o,enabled:n}),label:"Toggle outline"}),children:[Te("div",{className:"se-placeholder",children:"Outlines the currently selected object binding in the model editor."}),Te(O,{path:"sceneConfig.postProcessing.outline.selectionLayer",label:"Selection layer",value:o.selectionLayer,min:0,max:20,step:1,onChange:n=>t("outline",{...o,selectionLayer:n})}),Te(O,{path:"sceneConfig.postProcessing.outline.edgeStrength",label:"Edge strength",value:o.edgeStrength,min:0,max:10,step:.1,onChange:n=>t("outline",{...o,edgeStrength:n})}),Te(O,{path:"sceneConfig.postProcessing.outline.pulseSpeed",label:"Pulse speed",value:o.pulseSpeed,min:0,max:10,step:.1,onChange:n=>t("outline",{...o,pulseSpeed:n})}),Te(pt,{path:"sceneConfig.postProcessing.outline.visibleEdgeColor",label:"Visible edge color",value:o.visibleEdgeColor,onChange:n=>t("outline",{...o,visibleEdgeColor:n})}),Te(pt,{path:"sceneConfig.postProcessing.outline.hiddenEdgeColor",label:"Hidden edge color",value:o.hiddenEdgeColor,onChange:n=>t("outline",{...o,hiddenEdgeColor:n})}),Te(st,{path:"sceneConfig.postProcessing.outline.kernelSize",label:"Kernel size",value:o.kernelSize,options:Wn,onChange:n=>t("outline",{...o,kernelSize:n})}),Te(be,{path:"sceneConfig.postProcessing.outline.blur",label:"Blur",checked:o.blur,onChange:n=>t("outline",{...o,blur:n})}),Te(be,{path:"sceneConfig.postProcessing.outline.xRay",label:"X-Ray",checked:o.xRay,onChange:n=>t("outline",{...o,xRay:n})})]})}function Ec({pp:e,set:t,open:i,toggle:a}){let{selectiveBloom:o}=e;return Ic(oe,{title:"Selective bloom",tooltip:"Applies bloom only to objects assigned to the selected layer.",open:i.selectiveBloom,onToggle:()=>a("selectiveBloom"),disabled:!o.enabled,trailing:Te(se,{checked:o.enabled,onChange:n=>t("selectiveBloom",{...o,enabled:n}),label:"Toggle selective bloom"}),children:[Te("div",{className:"se-placeholder",children:"Applies bloom to the currently selected object binding."}),Te(O,{path:"sceneConfig.postProcessing.selectiveBloom.selectionLayer",label:"Selection layer",value:o.selectionLayer,min:0,max:20,step:1,onChange:n=>t("selectiveBloom",{...o,selectionLayer:n})}),Te(O,{path:"sceneConfig.postProcessing.selectiveBloom.intensity",label:"Intensity",value:o.intensity,min:0,max:5,step:.05,onChange:n=>t("selectiveBloom",{...o,intensity:n})}),Te(O,{path:"sceneConfig.postProcessing.selectiveBloom.luminanceThreshold",label:"Threshold",value:o.luminanceThreshold,min:0,max:1,step:.01,onChange:n=>t("selectiveBloom",{...o,luminanceThreshold:n})}),Te(O,{path:"sceneConfig.postProcessing.selectiveBloom.luminanceSmoothing",label:"Smoothing",value:o.luminanceSmoothing,min:0,max:1,step:.01,onChange:n=>t("selectiveBloom",{...o,luminanceSmoothing:n})}),Te(st,{path:"sceneConfig.postProcessing.selectiveBloom.kernelSize",label:"Kernel size",value:o.kernelSize,options:Wn,onChange:n=>t("selectiveBloom",{...o,kernelSize:n})}),Te(be,{path:"sceneConfig.postProcessing.selectiveBloom.mipmapBlur",label:"Mipmap blur",checked:o.mipmapBlur,onChange:n=>t("selectiveBloom",{...o,mipmapBlur:n})}),Te(be,{path:"sceneConfig.postProcessing.selectiveBloom.inverted",label:"Inverted",checked:o.inverted,onChange:n=>t("selectiveBloom",{...o,inverted:n})}),Te(be,{path:"sceneConfig.postProcessing.selectiveBloom.ignoreBackground",label:"Ignore background",checked:o.ignoreBackground,onChange:n=>t("selectiveBloom",{...o,ignoreBackground:n})})]})}function jc({pp:e,set:t,open:i,toggle:a}){let{smaa:o}=e;return Te(oe,{title:"Anti-aliasing",tooltip:"Reduces jagged edges with subpixel anti-aliasing.",open:i.smaa,onToggle:()=>a("smaa"),trailing:Te(se,{checked:o.enabled,onChange:n=>t("smaa",{...o,enabled:n}),label:"Toggle smaa"}),children:Te("div",{className:"se-placeholder",children:"Subpixel Morphological Anti-Aliasing smooths jagged edges in post-process."})})}import{jsx as _t,jsxs as ni}from"react/jsx-runtime";var zc=[{key:"toneMapping",label:"Tone mapping",group:"Color",Section:hc},{key:"brightnessContrast",label:"Brightness and contrast",group:"Color",Section:bc},{key:"hueSaturation",label:"Hue and saturation",group:"Color",Section:gc},{key:"colorAverage",label:"Color average",group:"Color",Section:uc},{key:"sepia",label:"Sepia",group:"Color",Section:xc},{key:"vignette",label:"Vignette",group:"Color",Section:mc},{key:"bloom",label:"Bloom",group:"Lighting",Section:fc},{key:"ssao",label:"Ambient occlusion",hint:"SSAO",group:"Lighting",feature:"postLighting",Section:vc},{key:"depthOfField",label:"Depth of field",group:"Lighting",feature:"postLighting",Section:kc},{key:"autofocus",label:"Auto focus",group:"Lighting",feature:"postLighting",Section:yc},{key:"godRays",label:"God rays",group:"Lighting",feature:"postLighting",Section:wc},{key:"lensflare",label:"Lens flare",group:"Lighting",feature:"postLighting",Section:Sc},{key:"outline",label:"Outline",group:"Selection",feature:"postSelection",Section:Oc},{key:"selectiveBloom",label:"Selective bloom",group:"Selection",feature:"postSelection",Section:Ec},{key:"smaa",label:"Anti-aliasing",hint:"SMAA",group:"Selection",feature:"postSelection",Section:jc},{key:"chromaticAberration",label:"Chromatic aberration",group:"Stylize",feature:"postSelection",Section:Bc},{key:"dotScreen",label:"Dot screen",group:"Stylize",feature:"postSelection",Section:Cc},{key:"glitch",label:"Glitch",group:"Stylize",feature:"postSelection",Section:Mc},{key:"grid",label:"Grid",group:"Stylize",feature:"postSelection",Section:Pc},{key:"noise",label:"Noise",group:"Stylize",feature:"postSelection",Section:Tc},{key:"pixelation",label:"Pixelation",group:"Stylize",feature:"postSelection",Section:Nc},{key:"ramp",label:"Color ramp",group:"Stylize",feature:"postSelection",Section:Ac},{key:"scanline",label:"Scan lines",group:"Stylize",feature:"postSelection",Section:Rc}],zm=["Color","Lighting","Selection","Stylize"],Lm={postLighting:"starter",postSelection:"growth"};function Ba({config:e,onChange:t}){let[i,a]=rr({}),[o,n]=rr(()=>new Set),[d,s]=rr(!1),[p,c]=rr(null),x=Em(null);hn([x],()=>s(!1),d),Om(()=>{if(!d)return;let m=N=>{N.key==="Escape"&&s(!1)};return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[d]);let h=m=>a(N=>({...N,[m]:!N[m]})),{tier:g}=it(),C=e.postProcessing,M=(m,N)=>t({...e,postProcessing:{...C,[m]:N}}),y=m=>!m.feature||nt(g,m.feature),T=zc.filter(m=>y(m)&&(C[m.key]?.enabled===!0||o.has(m.key))),f=zc.filter(m=>!T.includes(m)),u={pp:C,set:M,open:i,toggle:h},v=m=>{if(s(!1),!y(m)){c(m);return}c(null),n(N=>new Set(N).add(m.key)),a(N=>({...N,[m.key]:!0})),M(m.key,{...C[m.key],enabled:!0})};return ni("div",{className:"se-generalContent",children:[ni("div",{className:"se-listHeader",ref:x,children:[_t("span",{children:"Effects"}),ni("button",{type:"button",className:"bb-button bb-button--ghost bb-button--small","aria-expanded":d,disabled:!f.length,onClick:()=>s(m=>!m),children:[_t(Im,{size:13,"aria-hidden":"true"}),"Add effect"]}),d?_t("div",{className:"se-addMenu",role:"menu","aria-label":"Add effect",children:zm.map(m=>{let N=f.filter(A=>A.group===m);return N.length?ni("div",{role:"group","aria-label":m,children:[_t("h6",{children:m}),N.map(A=>ni("button",{type:"button",role:"menuitem",onClick:()=>v(A),children:[_t("span",{children:A.label}),A.hint?_t("small",{children:A.hint}):null,y(A)?null:_t(jm,{size:12,"aria-label":"Needs an upgrade"})]},A.key))]},m):null})}):null]}),p?.feature?_t(We,{requiredTier:Lm[p.feature],feature:p.label}):null,T.length?null:_t("p",{className:"se-listEmpty",children:"Add an effect to shape the final image, starting with tone mapping or bloom."}),T.map(({key:m,Section:N})=>_t(N,{...u},m))]})}import{useState as Lc,useSyncExternalStore as Dm}from"react";import{Eye as Fm,EyeOff as Hm,Plus as $m,Trash2 as Um}from"lucide-react";import{Fragment as Gm,jsx as xe,jsxs as ro}from"react/jsx-runtime";var _m=["512","1024","2048","4096"],Dc={none:"None",directional:"Directional",point:"Point",spot:"Spot",hemisphere:"Hemisphere"};function Vm({index:e,light:t,selected:i,onSelect:a,onToggleVisible:o}){return ro("div",{className:`se-lightRow ${i?"se-lightRow--active":""}`,onClick:a,children:[ro("span",{className:"se-lightRowLabel",children:[e+1,": ",Dc[t.type]]}),xe("button",{type:"button",className:"se-iconButton","aria-label":t.visible?"Hide light":"Show light",onClick:n=>{n.stopPropagation(),o()},children:t.visible?xe(Fm,{size:14}):xe(Hm,{size:14})})]})}function Km(){return{id:crypto.randomUUID(),type:"directional",color:"#ffffff",intensity:1,position:[5,10,5],attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0}}function Ta({config:e,onChange:t}){let[i,a]=Lc({lights:!0,shadows:!1,groundShadows:!1,environment:!1,envShadow:!1}),o=Dm(ld,dd),[n,d]=Lc(e.lighting.lights[0]?.id??null),s=o??n,p=B=>{d(B),sd(B)},c=B=>a(P=>({...P,[B]:!P[B]})),{tier:x}=it(),{lighting:h,shadows:g,groundShadows:C,environment:M}=e,y=B=>t({...e,lighting:B}),T=B=>t({...e,shadows:B}),f=B=>t({...e,groundShadows:B}),u=B=>t({...e,environment:B}),v=(B,P)=>{y({...h,lights:h.lights.map($=>$.id===B?{...$,...P}:$)})},m=h.lights.find(B=>B.id===s)??null,N=()=>{let B=Km();y({...h,lights:[...h.lights,B]}),p(B.id)},A=()=>{if(!m)return;let B=h.lights.filter(P=>P.id!==m.id);y({...h,lights:B}),p(B[0]?.id??null)},G=St(x,"lights",h.lights.length);return ro("div",{className:"se-generalContent",children:[ro(oe,{title:"Lights",open:i.lights,onToggle:()=>c("lights"),trailing:ro("span",{className:"se-listHeaderActions",children:[m&&h.lights.length>1?xe("button",{type:"button",className:"se-iconButton",onClick:A,title:"Remove selected light","aria-label":"Remove selected light",children:xe(Um,{size:13})}):null,xe("button",{type:"button",className:"se-iconButton",onClick:N,disabled:!G,title:"Add light","aria-label":"Add light",children:xe($m,{size:14})})]}),children:[xe("div",{className:"se-lightList",children:h.lights.map((B,P)=>xe(Vm,{index:P,light:B,selected:B.id===s,onSelect:()=>p(B.id),onToggleVisible:()=>v(B.id,{visible:!B.visible})},B.id))}),G?null:xe(We,{requiredTier:Ho("lights",h.lights.length),feature:"More lights"}),m?ro("div",{className:"se-lightProps",children:[ro("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.lighting.lights[\u2026].type",children:[xe("span",{className:"se-fieldLabel",children:"Type"}),xe("select",{className:"se-select",value:m.type,onChange:B=>v(m.id,{type:B.target.value}),children:Al.map(B=>xe("option",{value:B,children:Dc[B]},B))})]}),xe(pt,{path:"sceneConfig.lighting.lights[\u2026].color",label:"Color",value:m.color,onChange:B=>v(m.id,{color:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].intensity",label:"Intensity",value:m.intensity,min:0,max:10,step:.1,onChange:B=>v(m.id,{intensity:B})}),m.type!=="hemisphere"&&m.type!=="none"&&xe(kt,{path:"sceneConfig.lighting.lights[\u2026].position",label:"Position",value:m.position,min:-100,max:100,step:.05,onChange:B=>v(m.id,{position:B})}),m.type==="spot"&&ro(Gm,{children:[xe(O,{path:"sceneConfig.lighting.lights[\u2026].angle",label:"Angle",value:m.angle??Math.PI/6,min:0,max:Math.PI/2,step:.01,formatValue:B=>`${Math.round(B*180/Math.PI)}\xB0`,onChange:B=>v(m.id,{angle:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].penumbra",label:"Penumbra",value:m.penumbra??.2,min:0,max:1,step:.01,onChange:B=>v(m.id,{penumbra:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].distance",label:"Distance",value:m.distance??0,min:0,max:100,step:.5,onChange:B=>v(m.id,{distance:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].decay",label:"Decay",value:m.decay??2,min:0,max:4,step:.1,onChange:B=>v(m.id,{decay:B})})]}),xe(be,{path:"sceneConfig.lighting.lights[\u2026].attachedToCamera",label:"Attached to camera",checked:m.attachedToCamera,onChange:B=>v(m.id,{attachedToCamera:B})}),xe(be,{path:"sceneConfig.lighting.lights[\u2026].castShadow",label:"Cast shadows",checked:m.castShadow,onChange:B=>v(m.id,{castShadow:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].shadowBias",label:"Shadow bias",value:m.shadowBias,min:-.01,max:.01,step:1e-4,onChange:B=>v(m.id,{shadowBias:B})})]}):null]}),ro(oe,{title:"Shadows",open:i.shadows,onToggle:()=>c("shadows"),disabled:!g.enabled,trailing:xe(se,{checked:g.enabled,onChange:B=>T({...g,enabled:B}),label:"Toggle shadows"}),children:[xe(st,{label:"Map size",value:String(g.mapSize),options:_m,onChange:B=>T({...g,mapSize:Number(B)})}),xe(O,{path:"sceneConfig.shadows.bias",label:"Bias",value:g.bias,min:-.01,max:.01,step:1e-4,onChange:B=>T({...g,bias:B})}),xe(O,{path:"sceneConfig.shadows.normalBias",label:"Normal bias",value:g.normalBias,min:0,max:.2,step:.01,onChange:B=>T({...g,normalBias:B})}),xe(O,{path:"sceneConfig.shadows.radius",label:"Radius (softness)",value:g.radius,min:0,max:20,step:.5,onChange:B=>T({...g,radius:B})})]})]})}import{lazy as qm,Suspense as Wm}from"react";import{jsx as Ra}from"react/jsx-runtime";function ko(e){let t=qm(e);return function(a){return Ra(Wm,{fallback:Ra("p",{className:"bb-panelEmpty",children:"Loading\u2026"}),children:Ra(t,{...a})})}}import{jsx as Ko,jsxs as Zm}from"react/jsx-runtime";var Ym=ko(()=>import("./RulesTab-YVBZGJZX.mjs")),Fc=[{id:"model",label:"Model"},{id:"camera",label:"Camera"},{id:"world",label:"World"},{id:"lighting",label:"Lights"},{id:"postProcessing",label:"Effects"},{id:"rules",label:"Rules"}],Jm=[],Xm={};function Na({diagnostics:e,onDiagnosticsOpenChange:t,config:i,onChange:a,activeSubTab:o,materialVariantGroups:n=Jm,onImageFile:d,objectBindings:s=Xm}){let{tier:p}=it();return Zm("div",{className:"se-tabContent",children:[o==="model"&&Ko(dc,{diagnostics:e,onDiagnosticsOpenChange:t,config:i,onChange:a,materialVariantGroups:n}),o==="camera"&&Ko(cc,{config:i,onChange:a}),o==="world"&&Ko(pc,{config:i,onChange:a,onImageFile:d}),o==="lighting"&&Ko(Ta,{config:i,onChange:a}),o==="postProcessing"&&Ko(Ba,{config:i,onChange:a}),o==="rules"&&(nt(p,"rules")?Ko(Ym,{config:i,onChange:a,objectBindings:s}):Ko(We,{requiredTier:"growth",feature:"Rules"}))]})}import{ChevronRight as Hc,Info as $c}from"lucide-react";import{jsx as Vt,jsxs as Pn}from"react/jsx-runtime";function Uc({title:e,trailing:t,children:i,disabled:a,open:o,onToggle:n,tooltip:d}){return Pn("div",{className:"bb-materialPanel","data-ri-section":e,children:[Pn("div",{className:"bb-materialPanelHeaderRow",children:[Pn("button",{type:"button",className:"bb-materialPanelHeader",onClick:n,"aria-expanded":o,title:d,children:[Vt(Hc,{size:13,className:`bb-materialPanelChevron ${o?"bb-materialPanelChevron--open":""}`}),Vt("span",{className:"bb-materialPanelTitle",children:e}),d?Vt($c,{size:11,className:"bb-materialPanelHelp","aria-hidden":"true"}):null]}),t?Vt("span",{className:"bb-materialPanelTrailing",children:t}):null]}),o?Vt("div",{className:`bb-materialPanelBody ${a?"bb-materialPanelBody--disabled":""}`,children:i}):null]})}function Ye({title:e,open:t,onToggle:i,trailing:a,children:o,tooltip:n}){return Pn("div",{className:"bb-section","data-ri-section":e,children:[Pn("div",{className:"bb-sectionHeaderRow",children:[Pn("button",{type:"button",className:"bb-sectionHeaderButton",onClick:i,"aria-expanded":t,title:n,children:[Vt(Hc,{size:13,className:`bb-sectionChevron ${t?"bb-sectionChevron--open":""}`}),Vt("h2",{className:"bb-sectionTitle",children:e}),n?Vt($c,{size:11,className:"bb-sectionHelp","aria-hidden":"true"}):null]}),a?Vt("span",{className:"bb-sectionHeaderTrailing",children:a}):null]}),t?Vt("div",{className:"bb-sectionBody",children:o}):null]})}import{Copy as Qm,Plus as ef,Scan as tf,Trash2 as of}from"lucide-react";import{Fragment as nf,jsx as Re,jsxs as Kt}from"react/jsx-runtime";function Aa(e){let t=e.assets.find(o=>o.url===e.activeUrl),i=t?.placement??{},a=e.assets.length<2?"Use Remove model to clear the last model":e.deleteIsPermanent?"Delete model":"Delete model (undoable)";return Kt("div",{className:"ri-assets",children:[Kt(Pd,{title:"Models",children:[Re("button",{type:"button",className:"se-iconButton",title:"Frame all models","aria-label":"Frame all models",onClick:e.onFrameAll,children:Re(tf,{size:13})}),Re("button",{type:"button",className:"se-iconButton",title:"Add model","aria-label":"Add model",disabled:e.busy||!!e.addRequiresTier,onClick:e.onAdd,children:Re(ef,{size:14})})]}),e.addRequiresTier?Re(We,{requiredTier:e.addRequiresTier,feature:"More models in a project"}):null,Re("ul",{className:"ri-assets-list","aria-label":"Models in this scene",children:e.assets.map(o=>Re("li",{children:Kt("button",{type:"button",className:o.url===e.activeUrl?"ri-assets-item is-active":"ri-assets-item","aria-pressed":o.url===e.activeUrl,onClick:()=>e.onSelect(o.url),children:[Re("span",{className:"ri-assets-itemName",children:o.displayName??o.placement.label??o.name}),Re("small",{children:o.placement.visible===!1?"Hidden":o.ready?null:"Loading"})]})},o.id))}),t&&Kt(nf,{children:[Kt(ma,{title:"Placement",children:[Re(xn,{label:"Name",children:Re("input",{className:"se-textInput","aria-label":"Model name",value:i.label??t.name,maxLength:512,onChange:o=>e.onChange(t.id,{label:o.target.value})})}),Re(be,{label:"Visible",checked:i.visible!==!1,onChange:o=>e.onChange(t.id,{visible:o})}),Re(kt,{min:-1e6,max:1e6,label:"Position",value:i.position??[0,0,0],step:.1,onChange:o=>e.onChange(t.id,{position:o})}),Re(kt,{min:-1e6,max:1e6,label:"Rotation",value:(i.rotation??[0,0,0]).map(o=>o*180/Math.PI),step:1,onChange:o=>e.onChange(t.id,{rotation:o.map(n=>n*Math.PI/180)})}),Re(kt,{min:-1e6,max:1e6,label:"Scale",value:i.scale??[1,1,1],step:.1,onChange:o=>{o.every(n=>n!==0)&&e.onChange(t.id,{scale:o})}})]}),Kt(ma,{title:"Align",children:[Re(xn,{label:"Grid spacing",children:Re("input",{className:"se-numberInput","aria-label":"Grid spacing",type:"number",min:.001,step:.1,value:e.composition.gridSize,onChange:o=>{let n=Number(o.target.value);Number.isFinite(n)&&n>0&&e.onGridSize(n)}})}),Kt(to,{children:[Re("button",{type:"button",className:"bb-button",onClick:()=>e.onSnap(t.id),children:"Snap to grid"}),Re("button",{type:"button",className:"bb-button",disabled:!t.ready,onClick:()=>e.onGround(t.url),children:"Place on ground"})]})]}),Kt(to,{children:[Kt("button",{type:"button",className:"bb-button",disabled:e.busy||!t.ready,onClick:()=>e.onDuplicate(t.url),children:[Re(Qm,{size:13,"aria-hidden":"true"}),"Duplicate"]}),Kt("button",{type:"button",className:"bb-button",disabled:e.busy||e.assets.length<2,title:a,onClick:()=>e.onDelete(t.url),children:[Re(of,{size:13,"aria-hidden":"true"}),"Delete"]})]}),Re("p",{className:"rui-footnote",title:"Instance ID",children:Re("code",{children:t.id})})]})]})}import{useEffect as rf,useId as af,useRef as _c,useState as sf}from"react";import{ChevronDown as lf,Download as df,FileArchive as cf,FileCode2 as pf,FileJson as Vc,Upload as uf}from"lucide-react";import{jsx as Mt,jsxs as ar}from"react/jsx-runtime";function Kc({action:e,groups:t,busy:i}){let[a,o]=sf(!1),n=_c(null),d=_c(null),s=af(),p=i||t.every(c=>c.options.every(x=>x.disabled));return rf(()=>{if(!a)return;let c=x=>{n.current?.contains(x.target)||o(!1)};return window.addEventListener("pointerdown",c),()=>window.removeEventListener("pointerdown",c)},[a]),ar("div",{className:"bb-exportMenuWrapper",ref:n,onKeyDown:c=>{c.key!=="Escape"||!a||(c.preventDefault(),c.stopPropagation(),o(!1),d.current?.focus())},children:[ar("button",{ref:d,type:"button",className:e==="Export"?"bb-button bb-button--primary":"bb-barButton",disabled:p,"aria-busy":i||void 0,onClick:()=>o(c=>!c),title:`${e} files`,"aria-label":`${e} files`,"aria-expanded":a,"aria-controls":a?s:void 0,children:[e==="Import"?Mt(uf,{size:14,"aria-hidden":"true"}):Mt(df,{size:14,"aria-hidden":"true"}),e,Mt(lf,{size:12})]}),a&&Mt("div",{className:"bb-exportMenu",id:s,role:"group","aria-label":`${e} options`,children:t.map((c,x)=>ar("div",{className:"bb-fileMenuScope",children:[Mt("div",{className:"bb-exportMenuTitle",children:c.title}),Mt("p",{className:"bb-exportMenuDescription",id:`${s}-${x}`,children:c.description}),c.options.map(h=>ar("button",{type:"button",className:"bb-exportMenuItem",disabled:h.disabled||i,"aria-label":`${e} ${h.label}`,"aria-describedby":`${s}-${x}`,onClick:()=>{o(!1),h.run()},children:[h.icon,h.label]},h.label))]},c.title))})]})}function Gc(e,t,i){return[...i?[{title:"Complete scene",description:"Every model, placement, texture, binding, and scene setting. Remote assets keep their URLs.",options:[{label:"Complete scene ZIP",icon:Mt(cf,{size:14}),disabled:e==="Import"?i.importDisabled:i.exportDisabled,run:e==="Import"?i.onImport:i.onExport}]}]:[],...t.map(a=>({title:a.title,description:a.description,options:e==="Import"?[{label:`${a.title} JSON`,icon:Mt(Vc,{size:14}),disabled:a.importDisabled,run:a.onImport}]:[{label:`${a.title} JSON`,icon:Mt(Vc,{size:14}),disabled:a.exportDisabled,run:a.onExportJson},{label:`${a.title} TypeScript`,icon:Mt(pf,{size:14}),disabled:a.exportDisabled,run:a.onExportTs}]}))]}function qc({scopes:e,sceneBundle:t,busy:i}){return Mt(Kc,{action:"Export",groups:Gc("Export",e,t),busy:i})}function Wc({scopes:e,sceneBundle:t,busy:i}){return Mt(Kc,{action:"Import",groups:Gc("Import",e,t),busy:i})}import{Box as bf,ChevronDown as gf,CodeXml as mf,Maximize2 as ff,MousePointer2 as hf,Move3d as xf,Redo2 as vf,Rotate3d as yf,Search as wf,SquareSplitHorizontal as Sf,Undo2 as kf}from"lucide-react";import{jsx as ve,jsxs as Bn}from"react/jsx-runtime";var sr=[{id:"select",label:"Select",shortcut:"V",icon:ve(hf,{size:15})},{id:"move",label:"Move",shortcut:"G",icon:ve(xf,{size:15})},{id:"rotate",label:"Rotate",shortcut:"R",icon:ve(yf,{size:15})},{id:"scale",label:"Scale",shortcut:"T",icon:ve(ff,{size:15})}],Cf=typeof navigator<"u"&&/Mac|iPhone|iPad/.test(navigator.platform)?"\u2318K":"Ctrl K";function Yc({modelName:e,modelMenu:t,canUndo:i,canRedo:a,undoTarget:o,onUndo:n,onRedo:d,tool:s,onToolChange:p,space:c,onSpaceChange:x,hasModel:h,compareOpen:g,onToggleCompare:C,codeOpen:M,onToggleCode:y,onOpenCommands:T,start:f,xrToolsSlot:u,fileActions:v}){return Bn("header",{className:"bb-topBar",children:[ve("span",{className:"bb-topBarLogo",role:"img","aria-label":"Binding Builder",children:ve(bf,{size:14,"aria-hidden":"true"})}),t?ve(Zn,{label:e,title:"Model actions",children:t}):ve("span",{className:"bb-topBarModel",children:e}),f,ve("span",{className:"bb-topBarDivider"}),ve("button",{type:"button",className:"bb-toolButton",disabled:!i,onClick:n,title:`Undo ${o} change (Cmd/Ctrl+Z)`,"aria-label":`Undo ${o} change`,children:ve(kf,{size:15})}),ve("button",{type:"button",className:"bb-toolButton",disabled:!a,onClick:d,title:`Redo ${o} change (Cmd/Ctrl+Shift+Z)`,"aria-label":`Redo ${o} change`,children:ve(vf,{size:15})}),ve("span",{className:"bb-topBarDivider"}),ve("div",{className:"bb-toolGroup",role:"radiogroup","aria-label":"Transform tool",children:sr.map(m=>ve("button",{type:"button",role:"radio","aria-checked":s===m.id,"aria-label":`${m.label} tool`,disabled:!h,className:`bb-toolButton ${s===m.id?"bb-toolButton--active":""}`,onClick:()=>p(m.id),title:`${m.label} (${m.shortcut})`,children:m.icon},m.id))}),Bn("label",{className:"bb-topBarSelect",title:"Transform axes",children:[ve("span",{className:"bb-visuallyHidden",children:"Transform axes"}),Bn("select",{value:c,onChange:m=>x(m.target.value),children:[ve("option",{value:"world",children:"World"}),ve("option",{value:"local",children:"Local"})]}),ve(gf,{size:12,"aria-hidden":"true"})]}),ve("span",{className:"bb-topBarSpacer"}),Bn("button",{type:"button",className:"bb-commandButton",onClick:T,"aria-keyshortcuts":"Meta+K Control+K",children:[ve(wf,{size:13,"aria-hidden":"true"}),ve("span",{children:"Search settings"}),ve("kbd",{children:Cf})]}),ve("span",{className:"bb-topBarSpacer"}),ve("span",{ref:u,className:"bb-topBarXR"}),h?Bn("button",{type:"button",className:`bb-barButton ${g?"bb-barButton--active":""}`,onClick:C,"aria-pressed":g,title:"Drag a divider across the preview to see it before and after your changes",children:[ve(Sf,{size:14,"aria-hidden":"true"}),"Compare"]}):null,Bn("button",{type:"button",className:`bb-barButton ${M?"bb-barButton--active":""}`,onClick:y,"aria-pressed":M,title:"Show the code this editor produces",children:[ve(mf,{size:14,"aria-hidden":"true"}),"Code"]}),v]})}import{useCallback as Jc,useRef as Mf,useState as Xc}from"react";import{Copy as Pf}from"lucide-react";async function lr(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}import{Fragment as Tf,jsx as Co,jsxs as Go}from"react/jsx-runtime";function Zc(){let[e,t]=Xc(null),[i,a]=Xc(null),o=Mf(null),n=Jc(s=>{let c=s.target.closest?.("[data-ri-path]")?.dataset.riPath??null;c!==o.current&&(o.current=c,t(c))},[]),d=Jc(s=>{let p=s.target.closest?.("[data-ri-path]");p?.dataset.riPath&&(s.preventDefault(),a({x:s.clientX,y:s.clientY,path:p.dataset.riPath}))},[]);return{path:e,menu:i,closeMenu:()=>a(null),onMouseOver:n,onContextMenu:d}}function Qc({x:e,y:t,path:i,onClose:a}){return Co("div",{className:"bb-pathMenuScrim",onPointerDown:a,onContextMenu:o=>{o.preventDefault(),a()},children:Go("div",{className:"bb-pathMenu",style:{left:e,top:t},role:"menu",onPointerDown:o=>o.stopPropagation(),children:[Go("button",{type:"button",role:"menuitem",autoFocus:!0,onKeyDown:o=>{o.key==="Escape"&&a()},onClick:()=>{lr(i),a()},children:[Co(Pf,{size:13,"aria-hidden":"true"}),"Copy path"]}),Co("code",{children:i})]})})}function Bf({path:e}){let t=e.lastIndexOf(".");return Go(Tf,{children:[e.slice(0,t+1),Co("em",{children:e.slice(t+1)})]})}function ep({saveState:e,objectCount:t,selectedCount:i,path:a,hints:o}){return Go("footer",{className:"bb-statusBar",children:[e?Go("span",{className:"bb-statusSave",children:[Co("i",{"aria-hidden":"true"}),e]}):null,Go("span",{children:[t," ",t===1?"object":"objects"]}),i>0?Go("span",{children:[i," selected"]}):null,Co("span",{className:"bb-statusPath","aria-live":"off",children:a?Co(Bf,{path:a}):null}),Co("span",{className:"bb-statusHints",children:o})]})}import{jsx as Rf}from"react/jsx-runtime";function ii({orientation:e,label:t,onPointerDown:i,onKeyDown:a}){return Rf("div",{className:`bb-resizer bb-resizer--${e}`,role:"separator","aria-orientation":e,"aria-label":t,tabIndex:0,onPointerDown:i,onKeyDown:a})}import{useCallback as Oa,useEffect as Nf,useRef as Af,useState as Of}from"react";var op="react-immersive:editor-panels";function tp(){try{return JSON.parse(localStorage.getItem(op)??"{}")}catch{return{}}}function dr(e,{size:t,min:i,max:a,edge:o,open:n=!0}){let[d,s]=Of(()=>{let g=tp()[e];return{size:g&&Number.isFinite(g.size)?Math.min(a,Math.max(i,g.size)):t,open:g?.open??n}}),p=Af(d);p.current=d,Nf(()=>{try{localStorage.setItem(op,JSON.stringify({...tp(),[e]:d}))}catch{}},[e,d]);let c=Oa(g=>s(C=>({...C,open:g})),[]),x=Oa(g=>{if(g.button!==0)return;g.preventDefault();let C=g.currentTarget;C.setPointerCapture(g.pointerId);let M=o==="top"?g.clientY:g.clientX,y=p.current.size,T=o==="right"?1:-1,f=v=>{let m=o==="top"?v.clientY:v.clientX,N=Math.min(a,Math.max(i,y+(m-M)*T));s(A=>({...A,size:N}))},u=()=>{C.removeEventListener("pointermove",f),C.removeEventListener("pointerup",u),C.removeEventListener("pointercancel",u)};C.addEventListener("pointermove",f),C.addEventListener("pointerup",u),C.addEventListener("pointercancel",u)},[o,i,a]),h=Oa(g=>{let C=o==="top"?"ArrowUp":o==="right"?"ArrowRight":"ArrowLeft",M=o==="top"?"ArrowDown":o==="right"?"ArrowLeft":"ArrowRight";if(g.key!==C&&g.key!==M)return;g.preventDefault(),g.stopPropagation();let y=(g.key===C?1:-1)*16;s(T=>({...T,size:Math.min(a,Math.max(i,T.size+y))}))},[o,i,a]);return{size:d.size,open:d.open,setOpen:c,startResize:x,onResizeKey:h}}import{useEffect as Ef}from"react";import{X as jf}from"lucide-react";import{jsx as Ea,jsxs as If}from"react/jsx-runtime";function np({toast:e,onDismiss:t}){return Ef(()=>{if(!e||e.tone!=="success")return;let i=window.setTimeout(t,3e3);return()=>window.clearTimeout(i)},[e,t]),e?If("div",{className:`bb-toast bb-toast--${e.tone}`,role:e.tone==="error"?"alert":"status",children:[Ea("span",{children:e.text}),Ea("button",{type:"button","aria-label":"Dismiss message",onClick:t,children:Ea(jf,{size:13})})]}):null}import{memo as zf,useMemo as Lf,useState as rp}from"react";import{Check as Df,Copy as Ff,X as Hf}from"lucide-react";function ri(e){return JSON.stringify(e,null,2)}function cr(e){return['import { defineObjectBindings } from "@liveroom-tech/react-immersive/utils";',"",`export const objectBindings = defineObjectBindings(${JSON.stringify(e,null,2)});`,""].join(`
|
|
1
|
+
import{a as Nd,b as Ad}from"./chunk-E24EFHB5.mjs";import{a as vn}from"./chunk-FXV4CLAK.mjs";import{a as hn,b as xn,c as to,d as Pd,e as ma,g as oe,h as se,i as Bd,j as Td,k as O,l as be,m as st,n as Rd,o as pt,p as kt,q as $o}from"./chunk-AL6UIGWP.mjs";import{A as vd,B as Md,a as la,c as qi,e as Jl,f as fn,g as Ji,h as Zl,i as Ql,j as pa,k as nd,n as sd,o as ld,p as dd,q as cd,r as pd,s as ud,t as bd,u as gd,v as ba,w as md,x as hd,z as xd}from"./chunk-35UERL2D.mjs";import{a as ed,b as ua,c as nt,d as td,e as St,f as Ho,g as od,h as it,i as We}from"./chunk-FGAJ2UT7.mjs";import{B as Wl,C as Xl,T as rd,h as sa,k as ho}from"./chunk-DS5XNP7A.mjs";import{a as id}from"./chunk-37YITTIK.mjs";import{G as Nl,Ga as da,H as Al,Ha as Wi,I as Ol,Ia as Yi,J as El,K as jl,Ka as ca,L as Il,La as Yl,M as Wn,N as zl,O as fo,P as Ll,Qa as Yn,S as Vi,Sa as Xi,T as Do,Ta as ad,Ua as fd,Va as ga,W as Fo,Wa as yd,X as Dl,Xa as wd,Y as Fl,Ya as Sd,Z as Hl,Za as kd,_a as Cd,a as Ui,e as Gn,l as Rl,na as Ki,qa as mn,ta as Vl,u as gn,v as $t,w as It,x as qn}from"./chunk-Q4QPI5GG.mjs";import{e as _i}from"./chunk-LX3GXQNU.mjs";import{p as Gi}from"./chunk-7JCFNZJM.mjs";import{B as Gl,E as ql,n as Kl}from"./chunk-6Q6YZ7O5.mjs";import{c as $l,d as Ul,g as _l,h as aa}from"./chunk-BNKTI3CY.mjs";function xo(e){return{annotations:e.annotations,animations:e.animations,activeVariants:e.model.activeVariants,measurements:e.measurements,selectionSets:e.selectionSets,product:e.product,sequences:e.sequences}}function Xe(e,t){return{...e,model:{...e.model,activeVariants:t?.activeVariants??[]},annotations:t?.annotations??[],animations:t?.animations??fo.animations,measurements:t?.measurements,selectionSets:t?.selectionSets,product:t?.product,sequences:t?.sequences}}function Ed(e){if(e===void 0)return!0;try{return Gi(e),!0}catch{return!1}}function jd(e){if(e===void 0)return!0;try{return mn(e),!0}catch{return!1}}function Id(e){if(e===void 0)return!0;try{return Ki(e),!0}catch{return!1}}var Hg="react-immersive:binding-builder",$g=2,vo="session",yo="model",wo="textures",ha="current",zd=1;function Ut(e){return e.kind==="file"?`file:${e.key}`:`url:${e.url}`}var Uo=null;function Jn(){return Uo||(Uo=new Promise((e,t)=>{if(typeof indexedDB>"u"){t(new Error("IndexedDB is not available in this environment."));return}let i=indexedDB.open(Hg,$g);i.onupgradeneeded=()=>{let a=i.result;a.objectStoreNames.contains(vo)||a.createObjectStore(vo),a.objectStoreNames.contains(yo)||a.createObjectStore(yo),a.objectStoreNames.contains(wo)||a.createObjectStore(wo)},i.onsuccess=()=>{let a=i.result;a.onversionchange=()=>{a.close(),Uo=null},e(a)},i.onerror=()=>t(i.error??new Error("Failed to open IndexedDB."))}),Uo.catch(()=>{Uo=null}),Uo)}function yn(e){return new Promise((t,i)=>{e.oncomplete=()=>t(),e.onerror=()=>i(e.error??new Error("IndexedDB transaction failed.")),e.onabort=()=>i(e.error??new Error("IndexedDB transaction aborted."))})}function xa(e){return new Promise((t,i)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>i(e.error??new Error("IndexedDB request failed."))})}function lt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function va(e){return!lt(e)||typeof e.name!="string"?!1:e.kind==="file"?typeof e.key=="string":e.kind==="url"?typeof e.url=="string":!1}function Ld(e){return lt(e)&&va(e.model)&&typeof e.namePrefix=="string"}function Ug(e){if(e===void 0)return!0;try{return Ll(e),!0}catch{return!1}}function Dd(e){if(e===void 0)return!0;try{return _i(e),!0}catch{return!1}}function _g(e){return!lt(e)||!va(e.model)||!lt(e.bindings)||!lt(e.originalTransforms)||e.modelSettings!==void 0&&(!lt(e.modelSettings)||!Array.isArray(e.modelSettings.annotations)||!lt(e.modelSettings.animations)||!Array.isArray(e.modelSettings.animations.clips)||e.modelSettings.activeVariants!==void 0&&(!Array.isArray(e.modelSettings.activeVariants)||!e.modelSettings.activeVariants.every(t=>typeof t=="string")))||lt(e.modelSettings)&&!Id(e.modelSettings.measurements)||lt(e.modelSettings)&&!jd(e.modelSettings.selectionSets)||lt(e.modelSettings)&&!Ed(e.modelSettings.product)||lt(e.modelSettings)&&!Dd(e.modelSettings.sequences)?!1:e.mergeModels===void 0?!0:Array.isArray(e.mergeModels)&&e.mergeModels.every(Ld)}function Zi(e){if(!lt(e)||e.version!==zd)return!1;if(e.composition!==void 0)try{Fo(e.composition)}catch{return!1}return!(typeof e.savedAt!="number"||!lt(e.bindings)||!lt(e.sceneConfig)||!va(e.model)||!Id(e.sceneConfig.measurements)||!jd(e.sceneConfig.selectionSets)||!Ed(e.sceneConfig.product)||!Dd(e.sceneConfig.sequences)||!Ug(e.sceneConfig.section)||e.parkedModels!==void 0&&(!Array.isArray(e.parkedModels)||!e.parkedModels.every(_g))||e.mergeModels!==void 0&&(!Array.isArray(e.mergeModels)||!e.mergeModels.every(Ld))||e.modelOrder!==void 0&&(!Array.isArray(e.modelOrder)||!e.modelOrder.every(t=>typeof t=="string")))}function fa(e,t){return e.kind==="url"?Promise.resolve(null):xa(t.get(e.key)).then(i=>!i||i.key!==e.key?null:new File([i.blob],i.name,{type:i.type,lastModified:i.lastModified}))}async function Fd(e,t){let i=await Jn(),a={...e,version:zd,savedAt:Date.now()},o=i.transaction([vo,yo],"readwrite"),n=yn(o);o.objectStore(vo).put(a,ha);let d=o.objectStore(yo),s=new Set,p=x=>{x.kind==="file"&&s.add(x.key)};p(a.model),a.mergeModels?.forEach(x=>p(x.model)),a.parkedModels?.forEach(x=>{p(x.model),x.mergeModels?.forEach(h=>p(h.model))});for(let{key:x,file:h}of t??[]){let g={key:x,blob:h,name:h.name,type:h.type,lastModified:h.lastModified};d.put(g,x)}let c=d.getAllKeys();return c.onsuccess=()=>{for(let x of c.result)s.has(x)||d.delete(x)},await n,a}function Od(e,t){return Promise.all(e.map(async i=>({entry:i,file:await fa(i.model,t)})))}async function Hd(){let e=await Jn(),t=e.transaction(vo,"readonly"),i=yn(t),a=await xa(t.objectStore(vo).get(ha));if(await i,!Zi(a))return null;let o=a.parkedModels??[],n=a.mergeModels??[],d=e.transaction(yo,"readonly"),s=yn(d),p=d.objectStore(yo),[c,x,h]=await Promise.all([fa(a.model,p),Od(n,p),Promise.all(o.map(async g=>({entry:g,file:await fa(g.model,p),mergeFiles:await Od(g.mergeModels??[],p)})))]);return await s,a.model.kind==="file"&&!c?null:{session:{...a,parkedModels:o,mergeModels:n},file:c,parkedFiles:h,mergeFiles:x}}async function $d(){let t=(await Jn()).transaction([vo,yo,wo],"readwrite"),i=yn(t);t.objectStore(vo).delete(ha),t.objectStore(yo).clear(),t.objectStore(wo).clear(),await i}async function wn(e,t){let a=(await Jn()).transaction(wo,"readwrite"),o=yn(a),n={blob:t,name:t.name,type:t.type,savedAt:Date.now()};a.objectStore(wo).put(n,e),await o}async function oo(e){let i=(await Jn()).transaction(wo,"readonly"),a=yn(i),o=await xa(i.objectStore(wo).get(e));return await a,o?new File([o.blob],o.name,{type:o.type,lastModified:o.savedAt}):null}function Vo(e){return`url:${e}`}function wa(e){return e.models.find(t=>!e.composition.placements[Vo(t.url)]?.deleted)??e.models[0]}function Sa(e){return Fo(e.composition)}function er(e,t){return Xe(e,t.modelSettings)}function Vg(e){return{url:e.url,namePrefix:e.namePrefix,resolved:{url:e.url,name:e.namePrefix,format:"glb",cleanup:()=>{}},sessionModel:{kind:"url",url:e.url,name:e.namePrefix},nodeNames:[],loadState:"loading"}}function Sn(e){return(e.mergeModels??[]).map(Vg)}function ka(e){let t=e.name??"model";return{url:e.url,name:t,bindings:e.objectBindings,originalTransforms:{},sessionModel:{kind:"url",url:e.url,name:t},mergedModelSources:Sn(e),modelSettings:e.modelSettings}}function Ca(e){let t=new Map;for(let i of e.models){let{url:a,name:o,assetId:n,tilesetUrl:d,assetVersion:s}=i;t.set(a,{url:a,name:o,assetId:n,tilesetUrl:d,assetVersion:s});for(let p of i.mergeModels??[])t.set(p.url,{url:p.url,assetId:p.assetId})}return t}function Ud(e){let t=a=>a.map(o=>({url:o.url,assetId:e.sources.get(o.url)?.assetId??null,namePrefix:o.namePrefix})),i=e.modelOrder.flatMap(a=>{if(e.composition.placements[Vo(a)]?.deleted)return[];let o=e.sources.get(a)??{url:a};if(a===e.modelUrl)return[{...o,url:a,name:e.modelName,objectBindings:e.bindings,mergeModels:t(e.mergedModelSources),modelSettings:xo(e.sceneConfig)}];let n=e.parkedModels.find(d=>d.url===a);return n?[{...o,url:a,name:n.name,objectBindings:n.bindings,mergeModels:t(n.mergedModelSources),modelSettings:n.modelSettings}]:[]});return{projectId:e.project.id,baseRevision:e.project.revision,models:i,composition:{...e.composition,placements:Object.fromEntries(Object.entries(e.composition.placements).filter(([,a])=>!a.deleted))},sceneConfig:Xe(e.sceneConfig)}}function ya(e){return JSON.stringify(e,(t,i)=>i&&typeof i=="object"&&!Array.isArray(i)?Object.fromEntries(Object.entries(i).sort(([a],[o])=>a<o?-1:a>o?1:0)):i)}function tr(e,t){return e===t||ya(e)===ya(t)}function Kg(e){return xo(Xe(fo,e))}function kn(e){return ya({models:e.models.map(t=>({url:t.url,name:t.name,objectBindings:t.objectBindings,mergeModels:(t.mergeModels??[]).map(({url:i,namePrefix:a})=>({url:i,namePrefix:a})),modelSettings:Kg(t.modelSettings)})),composition:e.composition,sceneConfig:Xe(e.sceneConfig)})}function xv(e){if(!(e.models.length<2))return e.models.flatMap(t=>{let i=e.composition.placements[Vo(t.url)]??{};return i.deleted?[]:[{url:t.url,label:i.label??t.name,transform:i,visible:i.visible!==!1,objectBindings:t.objectBindings,sceneConfig:er(e.sceneConfig,t),mergeModels:t.mergeModels?.map(({url:a,namePrefix:o})=>({url:a,namePrefix:o}))}]})}var _d=new Set(["path","image","url","poster","src","imageUrl"]);function Gg(e){return e.startsWith("blob:")||e.startsWith("data:")||!!$t(e)}function _o(e,t=new Set){if(Array.isArray(e))e.forEach(i=>_o(i,t));else if(e&&typeof e=="object")for(let[i,a]of Object.entries(e))typeof a=="string"?_d.has(i)&&Gg(a)&&t.add(a):_o(a,t);return t}function Qi(e,t){return Array.isArray(e)?e.map(i=>Qi(i,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([i,a])=>[i,typeof a=="string"&&_d.has(i)&&t.has(a)?t.get(a):Qi(a,t)])):e}async function Vd(e){let t=$t(e)??e,i=await(await fetch(t)).blob(),a=e.startsWith("blob:")||e.startsWith("data:")?"image":e.split("/").pop()||"image";return new File([i],a,{type:i.type})}async function Kd(e,t){let i=x=>e.session.composition?.placements[Ut(x)]?.deleted;e={...e,parkedFiles:e.parkedFiles.filter(x=>!i(x.entry.model))};let a=new Map,o=async(x,h)=>{if(x.kind!=="file")return x;if(!h)throw new Error(`The scene bundle is missing ${x.name}.`);let{url:g}=await t(h);return a.set(`file:${x.key}`,Vo(g)),{kind:"url",url:g,name:x.name}},n=async x=>{let h=[];for(let{entry:g,file:C}of x)h.push({entry:{...g,model:await o(g.model,C)},file:null});return h},d=await o(e.session.model,e.file),s=await n(e.mergeFiles),p=[];for(let x of e.parkedFiles){let h=await o(x.entry.model,x.file),g=await n(x.mergeFiles);p.push({entry:{...x.entry,model:h,mergeModels:g.map(C=>C.entry)},file:null,mergeFiles:g})}let c=e.session.composition;return{file:null,mergeFiles:s,parkedFiles:p,session:{...e.session,model:d,mergeModels:s.map(x=>x.entry),parkedModels:p.map(x=>x.entry),modelOrder:e.session.modelOrder?.map(x=>a.get(x)??x),composition:c&&{...c,placements:Object.fromEntries(Object.entries(c.placements).map(([x,h])=>[a.get(x)??x,h]))}}}}import{strFromU8 as qg,strToU8 as Wg,unzip as Yg}from"fflate";var Xn=512*1024*1024,Gd=5*1024*1024;function Ma(e){return[e.model,...(e.mergeModels??[]).map(t=>t.model),...(e.parkedModels??[]).flatMap(t=>[t.model,...(t.mergeModels??[]).map(i=>i.model)])]}function qd(e){let t=o=>o.kind==="file"?`/bundle/${encodeURIComponent(o.key)}.glb`:o.url,i=[{model:e.model,bindings:e.bindings,merges:e.mergeModels,config:e.sceneConfig},...(e.parkedModels??[]).map(o=>({model:o.model,bindings:o.bindings,merges:o.mergeModels,config:Xe(e.sceneConfig,o.modelSettings)}))],a=i.map(o=>o.model.kind==="file"?`file:${o.model.key}`:`url:${o.model.url}`);if(new Set(a).size!==a.length||i.length>256)throw new Error("Scene instances must have unique identities (maximum 256).");if(e.modelOrder&&(new Set(e.modelOrder).size!==e.modelOrder.length||e.modelOrder.some(o=>!a.includes(o))))throw new Error("Invalid scene asset order.");for(let o of e.parkedModels??[])for(let n of Object.values(o.originalTransforms))for(let d of["position","rotation","scale"]){let s=n?.[d];if(s!==void 0&&(!Array.isArray(s)||s.length!==3||!s.every(p=>typeof p=="number"&&Number.isFinite(p))))throw new Error("Invalid original node transform.")}for(let o of i)Vl({version:1,objectBindings:o.bindings,configuration:{modelUrl:t(o.model),sceneConfig:o.config,mergeModels:o.merges?.map(n=>({url:t(n.model),namePrefix:n.namePrefix}))}})}async function Wd(e,t){let i=JSON.parse(JSON.stringify({...e,version:1,savedAt:Date.now()})),a={},o=[],n=[],d=0;async function s(g,C){if(d+=C.size,d>Xn)throw new Error("Scene bundle exceeds the 512 MiB expanded limit.");a[g]=new Uint8Array(await C.arrayBuffer())}for(let g of Ma(i)){if(g.kind!=="file"||o.some(y=>y.key===g.key))continue;let C=t.get(g.key);if(!C)throw new Error(`Cannot save scene: missing uploaded file ${g.name}.`);let M=`models/${o.length}`;o.push({key:g.key,path:M,name:C.name,type:C.type,lastModified:C.lastModified}),await s(M,C)}let p=new Map;async function c(g,C=0){if(C>64)throw new Error("Scene data is too deeply nested.");if(!(!g||typeof g!="object"))for(let[M,y]of Object.entries(g)){if(["__proto__","prototype","constructor"].includes(M))throw new Error("Reserved scene property.");if(M!=="metadata")if(typeof y=="string"){if(!["path","image","url","poster","src","imageUrl","customEnvironmentUrl"].includes(M))continue;let T=$t(y),f=T||y.startsWith("blob:")||y.startsWith("data:")?null:await oo(y);if(!f&&!T&&!y.startsWith("blob:")&&!y.startsWith("data:"))continue;let u=p.get(y);if(u){g[M]=u;continue}if(!f){let N=await fetch(T??y);if(!N.ok)throw new Error("Cannot read an uploaded texture for this scene.");let A=await N.blob();f=new File([A],`texture-${n.length}`,{type:A.type})}let v=`textures/${n.length}`,m=`/__ri_bundle_texture__/${n.length}`;n.push({ref:m,path:v,name:f.name,type:f.type}),await s(v,f),p.set(y,m),g[M]=m}else await c(y,C+1)}}for(let g of Ma(i))if(g.kind==="url"&&g.url.startsWith("blob:"))throw new Error("Cannot save a temporary model URL without its original file.");if(await c(i),!Zi(i))throw new Error("Invalid scene snapshot.");qd(i);let x=Wg(JSON.stringify({format:"react-immersive-scene",version:1,session:i,files:o,textures:n}));if(x.byteLength>Gd)throw new Error("Scene settings exceed the 5 MiB limit.");if(d+x.byteLength>Xn||Object.keys(a).length+1>1024)throw new Error("Scene bundle exceeds its size or file-count limit.");a["scene.json"]=x;let h=await Ji(a);if(h.byteLength>Xn)throw new Error("Compressed scene bundle exceeds 512 MiB.");return new Blob([h],{type:"application/zip"})}async function Yd(e){if(e.size>Xn)throw new Error("Scene ZIP exceeds 512 MiB.");let t=0,i=0,a="",o=new Set,n=new Uint8Array(await e.arrayBuffer()),d=await new Promise((y,T)=>Yg(n,{filter(f){return t+=f.originalSize,i++,o.has(f.name)?(a="Duplicate scene ZIP entry.",!1):(o.add(f.name),i>1024||t>Xn||f.name==="scene.json"&&f.originalSize>Gd||!/^(scene\.json|models\/\d+|textures\/\d+)$/.test(f.name)?(a="Invalid or oversized scene ZIP entries.",!1):!0)}},(f,u)=>f?T(f):a?T(new Error(a)):y(u)));if(!d["scene.json"])throw new Error("This ZIP does not contain a React Immersive scene.");let s=JSON.parse(qg(d["scene.json"]));if(s.format!=="react-immersive-scene"||s.version!==1||!Zi(s.session)||!Array.isArray(s.files)||!Array.isArray(s.textures))throw new Error("Invalid scene bundle manifest.");qd(s.session);let p=new Map,c=new Set;for(let y of s.files){if(!y||typeof y.key!="string"||!/^models\/\d+$/.test(y.path)||!d[y.path]||typeof y.name!="string"||typeof y.type!="string"||!Number.isFinite(y.lastModified)||c.has(y.path)||p.has(y.key))throw new Error("Invalid model file in scene bundle.");c.add(y.path),p.set(y.key,new File([d[y.path]],y.name,{type:y.type,lastModified:y.lastModified}))}for(let y of Ma(s.session))if(y.kind==="file"&&!p.has(y.key))throw new Error(`Scene bundle is missing ${y.name}.`);let x=new Map,h=crypto.randomUUID();for(let y of s.textures){if(!y||typeof y.ref!="string"||!/^\/__ri_bundle_texture__\/\d+$/.test(y.ref)||!/^textures\/\d+$/.test(y.path)||!d[y.path]||typeof y.name!="string"||typeof y.type!="string"||c.has(y.path)||x.has(y.ref))throw new Error("Invalid texture in scene bundle.");c.add(y.path),x.set(y.ref,{path:`materials/scene-${h}/${x.size}`,file:new File([d[y.path]],y.name,{type:y.type})})}function g(y,T=0){if(T>64)throw new Error("Scene data is too deeply nested.");if(!(!y||typeof y!="object"))for(let[f,u]of Object.entries(y)){if(["__proto__","constructor","prototype"].includes(f))throw new Error("Reserved scene property.");if(f!=="metadata")if(typeof u=="string"&&u.startsWith("/__ri_bundle_texture__/")){let v=x.get(u);if(!v)throw new Error("Scene bundle is missing a texture.");if(f==="path")y[f]=v.path;else{let m=d[[...s.textures].find(A=>A.ref===u).path],N="";for(let A=0;A<m.length;A+=32768)N+=String.fromCharCode(...m.subarray(A,A+32768));y[f]=`data:${v.file.type||"application/octet-stream"};base64,${btoa(N)}`}}else g(u,T+1)}}g(s.session),await Promise.all([...x.values()].map(y=>wn(y.path,y.file)));let C=y=>y.kind==="file"?p.get(y.key):null,M=y=>y.map(T=>({entry:T,file:C(T.model)}));return{session:s.session,file:C(s.session.model),mergeFiles:M(s.session.mergeModels??[]),parkedFiles:(s.session.parkedModels??[]).map(y=>({entry:y,file:C(y.model),mergeFiles:M(y.mergeModels??[])}))}}import{useCallback as Z,useEffect as ze,useMemo as Ue,useRef as ne,useState as U}from"react";import{Box3 as Su,Vector3 as Ox}from"three";import{Box as Ex,ChevronDown as jx,ClipboardPaste as Ix,Copy as zx,Ellipsis as Lx,Eye as Dx,PanelLeftClose as Fx,PanelLeftOpen as Hx,PanelRightClose as $x,PanelRightOpen as Ux,Pin as _x,PinOff as Vx,Trash2 as Kx}from"lucide-react";import{useEffect as Jg,useId as Xg,useRef as Jd,useState as Xd}from"react";import{Check as Zg,ChevronDown as Qg,History as em,ListRestart as tm,Plus as om,Trash2 as nm,Upload as im}from"lucide-react";import{Fragment as Qd,jsx as dt,jsxs as Ct}from"react/jsx-runtime";function Zn({label:e,icon:t,title:i,align:a="left",children:o}){let[n,d]=Xd(!1),s=Jd(null),p=Jd(null),c=Xg();return Jg(()=>{if(!n)return;let x=g=>{s.current?.contains(g.target)||d(!1)},h=g=>{g.key==="Escape"&&(d(!1),p.current?.focus())};return window.addEventListener("pointerdown",x),window.addEventListener("keydown",h),()=>{window.removeEventListener("pointerdown",x),window.removeEventListener("keydown",h)}},[n]),Ct("div",{className:"bb-headerMenuWrapper",ref:s,children:[Ct("button",{ref:p,type:"button",className:`bb-headerButton ${e?"":"bb-headerButton--icon"} ${n?"bb-headerButton--open":""}`,onClick:()=>d(x=>!x),title:i,"aria-label":e?void 0:i,"aria-expanded":n,"aria-controls":n?c:void 0,children:[t,e?Ct(Qd,{children:[e,dt(Qg,{size:12,"aria-hidden":"true"})]}):null]}),n?dt("div",{id:c,className:`bb-headerMenu bb-headerMenu--${a}`,role:"group","aria-label":i,children:o(()=>d(!1))}):null]})}function Zd({models:e,activeModelUrl:t,onSelectModel:i,onRestore:a,onRemove:o,onAddModel:n,onUpload:d,onReset:s,resetLabel:p,restoreDisabled:c,addModelDisabled:x,confirmRemove:h=!0,close:g}){let[C,M]=Xd(!1);return C&&o?Ct("div",{className:"bb-headerMenuConfirm",role:"alertdialog","aria-label":"Remove model",children:[dt("p",{children:"Remove the model and its bindings from the editor? This also clears the saved session. Export your work first if you want to keep it."}),Ct("div",{className:"bb-headerMenuConfirmActions",children:[dt("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>M(!1),children:"Cancel"}),dt("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{g(),o()},autoFocus:!0,children:"Remove"})]})]}):Ct(Qd,{children:[e?dt("div",{className:"bb-modelMenuList",role:"radiogroup","aria-label":"Active model",children:e.map(y=>Ct("button",{type:"button",role:"radio","aria-checked":y.url===t,className:"bb-headerMenuItem bb-modelMenuItem",title:y.label,onClick:()=>{g(),i?.(y.url)},children:[dt("span",{className:"bb-modelMenuCheck",children:y.url===t?dt(Zg,{size:14,"aria-hidden":"true"}):null}),dt("span",{className:"bb-modelMenuName",children:y.label})]},y.url))}):null,d?Ct("button",{type:"button",className:"bb-headerMenuItem",disabled:x,onClick:()=>{g(),d()},children:[dt(im,{size:14,"aria-hidden":"true"}),"Open model\u2026"]}):null,n?Ct("button",{type:"button",className:"bb-headerMenuItem",disabled:x,onClick:()=>{g(),n()},title:"Add another model, as a separate model or merged into this one",children:[dt(om,{size:14,"aria-hidden":"true"}),"Add model\u2026"]}):null,a?Ct("button",{type:"button",className:"bb-headerMenuItem",disabled:c,onClick:()=>{g(),a()},title:"Restore your last session: the model, its object bindings, and scene settings saved in this browser",children:[dt(em,{size:14,"aria-hidden":"true"}),"Restore last session"]}):null,s?Ct("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>{g(),s()},children:[dt(tm,{size:14,"aria-hidden":"true"}),p]}):null,o?Ct("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{if(h){M(!0);return}g(),o()},children:[dt(nm,{size:14,"aria-hidden":"true"}),"Remove model\u2026"]}):null]})}import{useCallback as rm,useEffect as am,useMemo as sm,useRef as ec}from"react";import{jsx as Pa,jsxs as lm}from"react/jsx-runtime";function tc({liveViewerRef:e,renderBefore:t,split:i,onSplitChange:a,labels:o,beforeAction:n,report:d,selected:s,onSelect:p,matchBy:c,onMatchByChange:x,showOutlines:h,onShowOutlinesChange:g}){let C=ec(null),M=ec(null),y=sm(()=>hd(),[]);am(()=>()=>y.detach(),[y]);let T=rm(f=>{M.current=f;let u=e.current;u&&y.attach(0,u.raw.controls,u.invalidate),y.attach(1,f.raw.controls,f.invalidate)},[y,e]);return lm("div",{ref:C,className:"ri-compare ri-compare--overlay",style:{"--ri-compare-split":`${i*100}%`},children:[Pa("div",{className:"ri-compare__layer ri-compare__layer--before",children:t(T)}),d&&Pa(md,{showOutlines:h,onShowOutlinesChange:g,matchBy:c,onMatchByChange:x,report:d,selected:s,onClear:()=>p?.(null),onSelect:f=>{let u=f.afterObjectId?0:1,v=u===0?e.current:M.current,m=u===0?f.afterObjectId:f.beforeObjectId,N=m?v?.raw.nodes[m]:null;y.setLeader(u),p?.(f),v&&N&&(v.raw.controls.fitToBox(N,!0),v.invalidate())}}),Pa(xd,{split:i,onSplitChange:a,labels:o,containerRef:C,beforeAction:n})]})}import{useCallback as no,useEffect as oc,useMemo as nc,useRef as or,useState as ic}from"react";var dm={currentClip:null,isPlaying:!1,speed:1,time:0,duration:0,active:[]};function cm(e,t){let i=[],a=new Map,o=new Map,n=new Map,d=new Set;for(let s of e){let p=t.get(s);if(!p)continue;let c=p.clipDetails??p.clips.map(h=>({sourceName:h,duration:0}));n.set(s,c);let x=new Map;for(let h of c){let g=h.sourceName;for(let C=2;d.has(g);C+=1)g=`${h.sourceName} (${C})`;d.add(g),i.push({sourceName:g,duration:h.duration}),a.set(g,{url:s,sourceName:h.sourceName}),x.set(h.sourceName,g)}o.set(s,x)}return{clipDetails:i,targets:a,displayNamesByUrl:o,clipDetailsByUrl:n}}function pm(e,t,i){let a=[];for(let o of e){let n=t.get(o),d=i.get(o);if(!(!n||!d))for(let s of n.active){let p=d.get(s.clip);p&&a.push({...s,clip:p})}}return a}function rc(e){let t=or(new Map),i=or(new Map),a=or(new Map),[o,n]=ic(0),[d,s]=ic(0),p=no((B,P)=>{if(t.current.get(B)===P)return;a.current.get(B)?.(),a.current.delete(B),t.current.set(B,P),i.current.set(B,P.getState?.()??dm);let $=P.subscribe?.(H=>{i.current.set(B,H),s(de=>de+1)});$&&a.current.set(B,$),n(H=>H+1)},[]);oc(()=>{let B=new Set(e),P=!1;for(let $ of[...t.current.keys()])B.has($)||(a.current.get($)?.(),a.current.delete($),t.current.delete($),i.current.delete($),P=!0);P&&n($=>$+1)},[e]),oc(()=>()=>a.current.forEach(B=>B()),[]);let{clipDetails:c,targets:x,displayNamesByUrl:h,clipDetailsByUrl:g,hasModels:C}=nc(()=>({...cm(e,t.current),hasModels:t.current.size>0}),[e,o]),M=or(x);M.current=x;let y=nc(()=>pm(e,i.current,h),[e,h,d]),T=no((B,P,$)=>{$(),!P.subscribe&&P.getState&&(i.current.set(B,P.getState()),s(H=>H+1))},[]),f=no(B=>{t.current.forEach((P,$)=>T($,P,()=>B(P,$)))},[T]),u=no((B,P)=>{let $=M.current.get(B);if(!$)return;let H=t.current.get($.url);H&&T($.url,H,()=>P(H,$))},[T]),v=no((B,P)=>u(B,($,H)=>$.play(H.sourceName,P)),[u]),m=no(B=>B===void 0?f(P=>P.pause()):u(B,(P,$)=>P.pause($.sourceName)),[f,u]),N=no(B=>B===void 0?f(P=>P.stop()):u(B,(P,$)=>P.stop($.sourceName)),[f,u]),A=no((B,P)=>P===void 0?f($=>$.setSpeed(B)):u(P,($,H)=>$.setSpeed(B,H.sourceName)),[f,u]),G=no((B,P)=>P===void 0?f($=>$.seek?.(B)):u(P,($,H)=>$.seek?.(B,H.sourceName)),[f,u]);return{clipDetails:c,clipDetailsByUrl:g,displayNamesByUrl:h,hasModels:C,active:y,play:v,pause:m,stop:N,setSpeed:A,seek:G,handleModelAnimationsReady:p}}import{useEffect as mm,useMemo as fm}from"react";function Qn(e,t){let i=new Map(e.animations.clips.map(n=>[n.sourceName,n])),a=t.map(({sourceName:n})=>i.get(n)??{sourceName:n,displayName:n,hidden:!1,loopMode:"repeat",speed:1}),o=e.animations.autoplayClip&&a.some(n=>n.sourceName===e.animations.autoplayClip&&!n.hidden)?e.animations.autoplayClip:null;return o===e.animations.autoplayClip&&a.length===e.animations.clips.length&&a.every((n,d)=>n===e.animations.clips[d])?e.animations:{clips:a,autoplayClip:o}}function nr(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function ei(e,t){if(!nr(e)||!nr(t))return t??e;let i={...e};for(let[a,o]of Object.entries(t)){if(o===void 0)continue;if(a==="section"){i[a]=Vi(i[a],o);continue}if(a==="sequences"){i[a]=_i(o);continue}let n=i[a];i[a]=nr(n)&&nr(o)?ei(n,o):o}return i}import{useCallback as So,useReducer as um,useRef as bm}from"react";var gm=100;function io(e,t){switch(t.type){case"history":return t.updater(e);case"set":{let i=typeof t.updater=="function"?t.updater(e.present):t.updater;if(i===e.present)return e;let a=t.track?e.edits+1:e.edits,o=!t.track&&e.edits===0?i:e.baseline;return t.track?t.coalesce?{...e,present:i,future:[],edits:a,baseline:o}:{past:[...e.past,e.present].slice(-gm),present:i,future:[],edits:a,baseline:o}:{...e,present:i,baseline:o}}case"undo":{if(e.past.length===0)return e;let i=e.past[e.past.length-1];return{...e,past:e.past.slice(0,-1),present:i,future:[e.present,...e.future],edits:e.edits+1}}case"redo":{if(e.future.length===0)return e;let[i,...a]=e.future;return{...e,past:[...e.past,e.present],present:i,future:a,edits:e.edits+1}}case"reset":return{past:[],present:t.value,future:[],edits:t.track?e.edits+1:0,baseline:t.track?e.baseline:t.value}}}function ti(e,t=600){let[i,a]=um(io,{past:[],present:e,future:[],edits:0,baseline:e}),o=bm(0),n=So(C=>{let M=Date.now(),y=M-o.current<t;o.current=M,a({type:"set",updater:C,coalesce:y,track:!0})},[t]),d=So(C=>{let M=Date.now()-o.current<t;a({type:"set",updater:C,coalesce:M,track:!1})},[t]),s=So(C=>{o.current=0,a({type:"set",updater:C,coalesce:!1,track:!0})},[]),p=So(C=>{a({type:"history",updater:C})},[]),c=So(C=>{o.current=0,a({type:"history",updater:typeof C=="function"?C:()=>C})},[]),x=So(()=>{o.current=0,a({type:"undo"})},[]),h=So(()=>{o.current=0,a({type:"redo"})},[]),g=So((C,M)=>{o.current=0,a({type:"reset",value:C,track:M?.asEdit??!1})},[]);return{value:i.present,setValue:n,setValueUntracked:d,setValueAsStep:s,updateHistory:p,restoreSnapshot:c,snapshot:i,undo:x,redo:h,reset:g,canUndo:i.past.length>0,canRedo:i.future.length>0,edits:i.edits,baseline:i.baseline}}function hm(e,t){return e.sourceName===t.sourceName&&e.displayName===t.displayName&&e.hidden===t.hidden&&e.loopMode===t.loopMode&&e.speed===t.speed}function ac(e,t,i,a){let o=Xe(t,e.modelSettings);if(o.animations===i)return e;let n={...o,animations:i},d=e.sceneHistory??{past:[],present:o,future:[],baseline:o,edits:0};return{...e,modelSettings:xo(n),sceneHistory:io(d,{type:"set",updater:n,track:a,coalesce:!1})}}function sc({modelUrl:e,sceneConfig:t,setSceneConfig:i,setSceneConfigUntracked:a,parkedModels:o,setParkedModels:n,animations:d,markSessionEdited:s}){let{clipDetailsByUrl:p,displayNamesByUrl:c}=d;mm(()=>{let g=e?p.get(e):void 0;g&&a(C=>{let M=Qn(C,g);return M===C.animations?C:{...C,animations:M}}),n(C=>{let M=!1,y=C.map(T=>{let f=p.get(T.url);if(!f)return T;let u=Xe(t,T.modelSettings),v=ac(T,t,Qn(u,f),!1);return M||(M=v!==T),v});return M?y:C})},[p,e,t,a,n]);let x=fm(()=>{let g=[],C=null;for(let[M,y]of c){let T=M===e?t:Xe(t,o.find(u=>u.url===M)?.modelSettings),f=Qn(T,p.get(M)??[]);for(let u of f.clips){let v=y.get(u.sourceName);v&&g.push({...u,sourceName:v,displayName:u.displayName===u.sourceName?v:u.displayName})}C??(C=f.autoplayClip?y.get(f.autoplayClip)??null:null)}return{clips:g,autoplayClip:C}},[c,p,e,t,o]);return{config:x,onChange:g=>{let C=new Map(x.clips.map(T=>[T.sourceName,T])),M=new Map(g.clips.map(T=>[T.sourceName,T])),y=(T,f)=>{let u=c.get(T);if(!u)return f.animations;let v=Qn(f,p.get(T)??[]),m=v.clips.map(A=>{let G=u.get(A.sourceName),B=G?M.get(G):void 0;if(!B)return A;let P={...B,sourceName:A.sourceName,displayName:B.displayName===C.get(G)?.displayName?A.displayName:B.displayName};return hm(A,P)?A:P}),N=g.autoplayClip===x.autoplayClip?v.autoplayClip:[...u].find(([,A])=>A===g.autoplayClip)?.[0]??null;return N===v.autoplayClip&&m.every((A,G)=>A===v.clips[G])?v:{clips:m,autoplayClip:N}};e&&i(T=>{let f=y(e,T);return f===T.animations?T:{...T,animations:f}}),n(T=>T.map(f=>ac(f,t,y(f.url,Xe(t,f.modelSettings)),!0))),s()}}}import{useEffect as xm,useRef as vm,useState as ir}from"react";import{ChevronLeft as ym,ChevronRight as wm,FileUp as Sm,RotateCcw as km,X as Cm}from"lucide-react";import{Fragment as Nm,jsx as V,jsxs as De}from"react/jsx-runtime";var Mm="image/png,image/jpeg,image/webp,image/avif,image/gif";function Pm(e){let t=e.trim();return!!(t&&$t(t))||/^(blob:|data:image\/)/i.test(t)}var Bm=["lit","unlit","normals"],Tm=["default","color","image","environment"],Rm={pbr:"PBR",matcap:"Matcap","uv-checker":"UV checker"};function lc(e){let t=e%360;return t<0?t+360:t}function dc({config:e,onChange:t,diagnostics:i,onDiagnosticsOpenChange:a,materialVariantGroups:o=[]}){let{model:n,wireframe:d}=e,s=Ul(n),p=o.length>0?s.filter(u=>!o.some(v=>v.variants.some(m=>m.name===u))):[],{tier:c}=it(),x=id(),[h,g]=ir({orientation:!0,diagnostics:!1,autoRotate:!1,wireframe:!1,section:!1});xm(()=>(a?.(h.diagnostics),()=>a?.(!1)),[h.diagnostics,a]);let C=u=>g(v=>({...v,[u]:!v[u]})),M=u=>t({...e,model:u}),y=u=>t({...e,wireframe:u}),T=e.section??zl,f=u=>t({...e,section:{...T,...u}});return De("div",{className:"se-generalContent",children:[De(oe,{title:"Display",open:h.orientation,onToggle:()=>C("orientation"),children:[De("div",{className:"se-field se-fieldInline",children:[De("div",{className:"se-fieldLabel se-fieldLabel--action",children:[V("span",{children:"Straighten"}),V("button",{type:"button",className:"se-iconButton",onClick:()=>M({...n,rotation:[0,0,0]}),"aria-label":"Reset model rotation",children:V(km,{size:12})})]}),V("div",{className:"se-axisStepperGrid",children:["X","Y","Z"].map((u,v)=>De("div",{className:"se-axisStepper",children:[V("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let m=[...n.rotation];m[v]=lc(m[v]-90),M({...n,rotation:m})},"aria-label":`Rotate ${u} axis backward`,children:V(ym,{size:12})}),V("span",{className:"se-axisStepperLabel",children:u}),V("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let m=[...n.rotation];m[v]=lc(m[v]+90),M({...n,rotation:m})},"aria-label":`Rotate ${u} axis forward`,children:V(wm,{size:12})})]},u))})]}),V(kt,{label:"Rotation",path:"sceneConfig.model.rotation",value:n.rotation,min:0,max:360,step:1,onChange:u=>M({...n,rotation:u})}),De("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.model.renderer",children:[V("span",{className:"se-fieldLabel",children:"Renderer"}),V("div",{className:"se-segmentedControl se-segmentedControl--renderer",children:Ol.map(u=>V("button",{type:"button",className:`se-segmentedOption ${n.renderer===u?"se-segmentedOption--active":""}`,onClick:()=>M({...n,renderer:u}),children:Rm[u]},u))})]}),V(st,{label:"Shading",path:"sceneConfig.model.shading",value:n.shading,options:Bm,onChange:u=>M({...n,shading:u})}),o.length>0&&!nt(c,"materialVariants")?V(We,{requiredTier:"starter",feature:"Material variants"}):null,(nt(c,"materialVariants")?o:[]).map((u,v)=>{let m=s.find(N=>u.variants.some(A=>A.name===N));return De("label",{className:"se-field se-fieldInline",children:[V("span",{className:"se-fieldLabel",children:u.name??"Material variant"}),De("select",{className:"se-select",value:m??"",onChange:N=>{let A=N.target.value,G=s.filter(B=>B!==m);M(aa(n,A?$l(G,A,o):G))},children:[V("option",{value:"",children:"Model default"}),u.variants.map(N=>V("option",{value:N.name,children:N.label},N.name))]})]},u.name??`group-${v}`)}),p.length>0?De("div",{className:"se-placeholder se-placeholder--spaced",children:["Not in this model: ",p.join(", "),"."," ",V("button",{type:"button",className:"se-linkButton",onClick:()=>M(aa(n,s.filter(u=>!p.includes(u)))),children:"Remove"})]}):null]}),De(oe,{title:"Auto rotate",open:h.autoRotate,onToggle:()=>C("autoRotate"),trailing:V(se,{checked:n.autoRotate??!1,onChange:u=>M({...n,autoRotate:u}),label:"Toggle auto rotate"}),children:[n.autoRotate&&x?V("div",{className:"se-placeholder se-placeholder--spaced",children:"Your device is set to reduce motion, so this preview won't turn. Visitors without that setting will see it."}):null,n.autoRotate?V(O,{label:"Speed",path:"sceneConfig.model.autoRotateSpeed",value:n.autoRotateSpeed??1,min:.1,max:3,step:.1,formatValue:u=>`${u.toFixed(1)}x`,onChange:u=>M({...n,autoRotateSpeed:u})}):V("div",{className:"se-placeholder",children:"Enable auto rotate to adjust its speed."})]}),V(oe,{title:"Wireframe",open:h.wireframe,onToggle:()=>C("wireframe"),disabled:!d.enabled,trailing:V(se,{checked:d.enabled,onChange:u=>y({...d,enabled:u}),label:"Toggle wireframe preview"}),children:De(Nm,{children:[V(O,{label:"Opacity",path:"sceneConfig.wireframe.opacity",value:d.opacity,min:0,max:1,step:.01,onChange:u=>y({...d,opacity:u})}),V(pt,{label:"Wire color",path:"sceneConfig.wireframe.color",value:d.color,onChange:u=>y({...d,color:u})})]})}),V(oe,{title:"Section cut",open:h.section,onToggle:()=>C("section"),disabled:!T.enabled,trailing:V(se,{checked:T.enabled,onChange:u=>{f({enabled:u}),u&&g(v=>({...v,section:!0}))},label:"Toggle section cut"}),children:V("div",{"data-ri-path":"sceneConfig.section",children:V(ud,{section:T,onChange:f})})}),i&&V(oe,{title:"Diagnostics",open:h.diagnostics,onToggle:()=>C("diagnostics"),children:V(Md,{...i})})]})}function cc({config:e,onChange:t}){let{camera:i}=e,[a,o]=ir(!0);return V("div",{className:"se-generalContent",children:V(oe,{title:"Lens",open:a,onToggle:()=>o(n=>!n),children:V(O,{label:"Field of view",path:"sceneConfig.camera.fieldOfView",value:i.fieldOfView,min:20,max:100,step:.1,formatValue:n=>`${n.toFixed(1)}\xB0`,onChange:n=>t({...e,camera:{...i,fieldOfView:n}})})})})}function pc({config:e,onChange:t,onImageFile:i}){let{background:a,environment:o,groundShadows:n}=e,d=vm(null),[s,p]=ir(null),c=Pm(a.imageUrl),{tier:x}=it(),[h,g]=ir({environment:!0,envShadow:!1,background:!0,groundShadows:!1}),C=u=>g(v=>({...v,[u]:!v[u]})),M=u=>t({...e,background:u}),y=u=>t({...e,environment:u}),T=u=>t({...e,groundShadows:u}),f=u=>{if(!u.type.startsWith("image/")){p("Choose a PNG, JPG, WEBP, AVIF or GIF image.");return}p(null);let v=gn(u);v===a.imageUrl&&$t(v)||It(v,URL.createObjectURL(u)),i?.(v,u),M({...a,imageUrl:v})};return De("div",{className:"se-generalContent",children:[De(oe,{title:"Environment",open:h.environment,onToggle:()=>C("environment"),children:[De("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.environment.source",children:[V("span",{className:"se-fieldLabel",children:"Source"}),V("div",{className:"se-segmentedControl",children:["preset","custom"].map(u=>V("button",{type:"button",className:`se-segmentedOption ${o.source===u?"se-segmentedOption--active":""}`,onClick:()=>y({...o,source:u}),children:u==="preset"?"Preset":"Custom"},u))})]}),o.source==="preset"?V(st,{label:"Preset",path:"sceneConfig.environment.preset",value:o.preset,options:El,onChange:u=>y({...o,source:"preset",preset:u})}):nt(x,"customEnvironment")?De("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.environment.customEnvironmentUrl",children:[V("span",{className:"se-fieldLabel",children:"URL"}),V("input",{type:"text",className:"se-textInput","aria-label":"Custom environment URL",placeholder:"https://example.com/studio.hdr",value:o.customEnvironmentUrl,onChange:u=>y({...o,customEnvironmentUrl:u.target.value})}),o.customEnvironmentUrl.trim()&&!Nl(o.customEnvironmentUrl)?V("span",{className:"bb-note bb-note--error se-fieldFull",children:"Use an HDR, EXR, JPG, PNG, or WEBP URL."}):null]}):V(We,{requiredTier:"starter",feature:"Custom environments"}),V(O,{label:"Intensity",path:"sceneConfig.environment.intensity",value:o.intensity,min:0,max:3,step:.05,onChange:u=>y({...o,intensity:u})}),V(O,{label:"Rotation",path:"sceneConfig.environment.rotation",value:o.rotation,min:0,max:360,step:1,formatValue:u=>`${u}\xB0`,onChange:u=>y({...o,rotation:u})}),V(be,{label:"As background",path:"sceneConfig.background.type",checked:a.enabled&&a.type==="environment",onChange:u=>M(u?{...a,enabled:!0,type:"environment"}:{...a,type:"color"})}),V("p",{className:"bb-note se-fieldFull",children:"It always lights the model; this also draws it behind."})]}),De(oe,{title:"Environment shadow",open:h.envShadow,onToggle:()=>C("envShadow"),disabled:!o.shadowLight.enabled,trailing:V(se,{checked:o.shadowLight.enabled,onChange:u=>y({...o,shadowLight:{...o.shadowLight,enabled:u}}),label:"Toggle environment shadow light"}),children:[V(O,{label:"Light intensity",path:"sceneConfig.environment.shadowLight.intensity",value:o.shadowLight.intensity,min:0,max:20,step:.1,onChange:u=>y({...o,shadowLight:{...o.shadowLight,intensity:u}})}),V(O,{label:"Shadow bias",path:"sceneConfig.environment.shadowLight.bias",value:o.shadowLight.bias,min:-.01,max:.01,step:1e-4,onChange:u=>y({...o,shadowLight:{...o.shadowLight,bias:u}})})]}),De(oe,{title:"Background",open:h.background,onToggle:()=>C("background"),children:[V(st,{label:"Show",path:"sceneConfig.background.type",value:a.enabled?a.type:"default",options:Tm,onChange:u=>M(u==="default"?{...a,enabled:!1}:{...a,enabled:!0,type:u})}),a.enabled?a.type==="image"&&!nt(x,"backgroundImages")?V(We,{requiredTier:"starter",feature:"Background images"}):a.type==="image"?De("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.background.imageUrl",children:[V("label",{className:"se-fieldLabel",htmlFor:"se-background-image-url",children:"Image"}),De("div",{className:"bb-fileField",children:[V("input",{id:"se-background-image-url",type:"text",className:"bb-input bb-fileField-input",placeholder:"Paste a link or upload",value:a.imageUrl,readOnly:c,onChange:u=>{p(null),M({...a,imageUrl:u.target.value})}}),c?V("button",{type:"button",className:"bb-fileFieldButton",onClick:()=>M({...a,imageUrl:""}),"aria-label":"Remove uploaded background image",title:"Remove uploaded image",children:V(Cm,{size:13})}):V("button",{type:"button",className:"bb-fileFieldButton",onClick:()=>d.current?.click(),"aria-label":"Upload background image",title:"Upload image",children:V(Sm,{size:13})}),V("input",{ref:d,type:"file",accept:Mm,className:"bb-hiddenInput",onChange:u=>{let v=u.target.files?.[0];u.target.value="",v&&f(v)}})]}),s?V("span",{className:"bb-note bb-note--error se-fieldFull",children:s}):c?V("span",{className:"bb-note se-fieldFull",children:"Uploaded files are bundled into the scene export."}):null]}):null:null,a.enabled&&a.type==="color"?V(pt,{label:"Color",path:"sceneConfig.background.color",value:a.color,onChange:u=>M({...a,color:u})}):null]}),De(oe,{title:"Ground shadows",open:h.groundShadows,onToggle:()=>C("groundShadows"),disabled:!n.enabled,trailing:V(se,{checked:n.enabled,onChange:u=>T({...n,enabled:u}),label:"Toggle ground shadows"}),children:[V(O,{label:"Intensity",path:"sceneConfig.groundShadows.intensity",value:n.intensity,min:0,max:1,step:.01,onChange:u=>T({...n,intensity:u})}),V(O,{label:"Border fade",path:"sceneConfig.groundShadows.borderFade",value:n.borderFade,min:0,max:10,step:.1,onChange:u=>T({...n,borderFade:u})}),V(O,{label:"Height",path:"sceneConfig.groundShadows.height",value:n.height,min:-5,max:5,step:.1,onChange:u=>T({...n,height:u})}),V(O,{label:"Size",path:"sceneConfig.groundShadows.size",value:n.size,min:1,max:50,step:.5,onChange:u=>T({...n,size:u})})]})]})}import{useEffect as Om,useRef as Em,useState as rr}from"react";import{Lock as jm,Plus as Im}from"lucide-react";import{jsx as ce,jsxs as Cn}from"react/jsx-runtime";var Am=["linear","reinhard","aces"];function uc({pp:e,set:t,open:i,toggle:a}){let{colorAverage:o}=e;return ce(oe,{title:"Color average",tooltip:"Blends the frame toward a single average color for a washed-out stylized look.",open:i.colorAverage,onToggle:()=>a("colorAverage"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("colorAverage",{...o,enabled:n}),label:"Toggle color average"}),children:ce("div",{className:"se-placeholder",children:"Averages the frame color using the docs default blend mode."})})}function bc({pp:e,set:t,open:i,toggle:a}){let{brightnessContrast:o}=e;return Cn(oe,{title:"Brightness and contrast",tooltip:"Raises or lowers overall brightness and contrast across the scene.",open:i.brightnessContrast,onToggle:()=>a("brightnessContrast"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("brightnessContrast",{...o,enabled:n}),label:"Toggle brightness contrast"}),children:[ce(O,{path:"sceneConfig.postProcessing.brightnessContrast.brightness",label:"Brightness",value:o.brightness,min:-1,max:1,step:.01,onChange:n=>t("brightnessContrast",{...o,brightness:n})}),ce(O,{path:"sceneConfig.postProcessing.brightnessContrast.contrast",label:"Contrast",value:o.contrast,min:-1,max:1,step:.01,onChange:n=>t("brightnessContrast",{...o,contrast:n})})]})}function gc({pp:e,set:t,open:i,toggle:a}){let{hueSaturation:o}=e;return Cn(oe,{title:"Hue and saturation",tooltip:"Shifts the hue and saturation to tint the whole image.",open:i.hueSaturation,onToggle:()=>a("hueSaturation"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("hueSaturation",{...o,enabled:n}),label:"Toggle hue saturation"}),children:[ce(O,{path:"sceneConfig.postProcessing.hueSaturation.hue",label:"Hue",value:o.hue,min:-Math.PI,max:Math.PI,step:.01,formatValue:n=>`${n.toFixed(2)} rad`,onChange:n=>t("hueSaturation",{...o,hue:n})}),ce(O,{path:"sceneConfig.postProcessing.hueSaturation.saturation",label:"Saturation",value:o.saturation,min:-1,max:1,step:.01,onChange:n=>t("hueSaturation",{...o,saturation:n})})]})}function mc({pp:e,set:t,open:i,toggle:a}){let{vignette:o}=e;return Cn(oe,{title:"Vignette",tooltip:"Darkens the edges of the screen so the center feels more focused.",open:i.vignette,onToggle:()=>a("vignette"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("vignette",{...o,enabled:n}),label:"Toggle vignette"}),children:[ce(O,{path:"sceneConfig.postProcessing.vignette.offset",label:"Offset",value:o.offset,min:0,max:1,step:.01,onChange:n=>t("vignette",{...o,offset:n})}),ce(O,{path:"sceneConfig.postProcessing.vignette.darkness",label:"Darkness",value:o.darkness,min:0,max:1,step:.01,onChange:n=>t("vignette",{...o,darkness:n})}),ce(be,{path:"sceneConfig.postProcessing.vignette.eskil",label:"Eskil",checked:o.eskil,onChange:n=>t("vignette",{...o,eskil:n})})]})}function fc({pp:e,set:t,open:i,toggle:a}){let{bloom:o}=e;return Cn(oe,{title:"Bloom",tooltip:"Makes bright areas glow and bleed softly into nearby pixels.",open:i.bloom,onToggle:()=>a("bloom"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("bloom",{...o,enabled:n}),label:"Toggle bloom"}),children:[ce(O,{path:"sceneConfig.postProcessing.bloom.luminanceThreshold",label:"Threshold",value:o.luminanceThreshold,min:0,max:1,step:.01,onChange:n=>t("bloom",{...o,luminanceThreshold:n})}),ce(O,{path:"sceneConfig.postProcessing.bloom.luminanceSmoothing",label:"Smoothing",value:o.luminanceSmoothing,min:0,max:1,step:.01,onChange:n=>t("bloom",{...o,luminanceSmoothing:n})}),ce(O,{path:"sceneConfig.postProcessing.bloom.intensity",label:"Intensity",value:o.intensity,min:0,max:3,step:.05,onChange:n=>t("bloom",{...o,intensity:n})}),ce(be,{path:"sceneConfig.postProcessing.bloom.mipmapBlur",label:"Mipmap blur",checked:o.mipmapBlur,onChange:n=>t("bloom",{...o,mipmapBlur:n})}),ce(O,{path:"sceneConfig.postProcessing.bloom.radius",label:"Radius",value:o.radius,min:0,max:1,step:.01,onChange:n=>t("bloom",{...o,radius:n})}),ce(O,{path:"sceneConfig.postProcessing.bloom.levels",label:"Levels",value:o.levels,min:1,max:16,step:1,onChange:n=>t("bloom",{...o,levels:n})})]})}function hc({pp:e,set:t,open:i,toggle:a}){let{toneMapping:o}=e;return Cn(oe,{title:"Tone mapping",tooltip:"Remaps HDR lighting to screen output and controls exposure style.",open:i.toneMapping,onToggle:()=>a("toneMapping"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("toneMapping",{...o,enabled:n}),label:"Toggle tone mapping"}),children:[Cn("div",{className:"se-field",children:[ce("span",{className:"se-fieldLabel",children:"Mode"}),ce("div",{className:"se-segmentedControl",children:Am.map(n=>ce("button",{type:"button",className:`se-segmentedOption ${o.mode===n?"se-segmentedOption--active":""}`,onClick:()=>t("toneMapping",{...o,mode:n}),children:n==="aces"?"Filmic":n.charAt(0).toUpperCase()+n.slice(1)},n))})]}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.resolution",label:"Resolution",value:o.resolution,min:64,max:4096,step:64,onChange:n=>t("toneMapping",{...o,resolution:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.whitePoint",label:"White point",value:o.whitePoint,min:0,max:16,step:.01,onChange:n=>t("toneMapping",{...o,whitePoint:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.middleGrey",label:"Middle grey",value:o.middleGrey,min:0,max:1,step:.01,onChange:n=>t("toneMapping",{...o,middleGrey:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.minLuminance",label:"Min luminance",value:o.minLuminance,min:0,max:1,step:.01,onChange:n=>t("toneMapping",{...o,minLuminance:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.averageLuminance",label:"Average luminance",value:o.averageLuminance,min:0,max:4,step:.01,onChange:n=>t("toneMapping",{...o,averageLuminance:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.adaptationRate",label:"Adaptation rate",value:o.adaptationRate,min:0,max:10,step:.01,onChange:n=>t("toneMapping",{...o,adaptationRate:n})}),ce(O,{path:"sceneConfig.postProcessing.toneMapping.exposure",label:"Exposure",value:o.exposure,min:0,max:3,step:.01,onChange:n=>t("toneMapping",{...o,exposure:n})})]})}function xc({pp:e,set:t,open:i,toggle:a}){let{sepia:o}=e;return ce(oe,{title:"Sepia",tooltip:"Adds a warm vintage brown tint to the entire image.",open:i.sepia,onToggle:()=>a("sepia"),disabled:!o.enabled,trailing:ce(se,{checked:o.enabled,onChange:n=>t("sepia",{...o,enabled:n}),label:"Toggle sepia"}),children:ce(O,{path:"sceneConfig.postProcessing.sepia.intensity",label:"Intensity",value:o.intensity,min:0,max:1,step:.01,onChange:n=>t("sepia",{...o,intensity:n})})})}import{jsx as Y,jsxs as oi}from"react/jsx-runtime";function vc({pp:e,set:t,open:i,toggle:a}){let{ssao:o}=e;return oi(oe,{title:"Ambient occlusion",tooltip:"Adds soft contact shadows in corners, creases, and tight spaces.",open:i.ssao,onToggle:()=>a("ssao"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("ssao",{...o,enabled:n}),label:"Toggle ssao"}),children:[Y(O,{path:"sceneConfig.postProcessing.ssao.samples",label:"Samples",value:o.samples,min:1,max:64,step:1,onChange:n=>t("ssao",{...o,samples:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.rings",label:"Rings",value:o.rings,min:1,max:12,step:1,onChange:n=>t("ssao",{...o,rings:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.intensity",label:"Intensity",value:o.intensity,min:0,max:20,step:.5,onChange:n=>t("ssao",{...o,intensity:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.radius",label:"Radius",value:o.radius,min:.01,max:1,step:.01,onChange:n=>t("ssao",{...o,radius:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.bias",label:"Bias",value:o.bias,min:0,max:.1,step:.001,onChange:n=>t("ssao",{...o,bias:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.luminanceInfluence",label:"Luminance influence",value:o.luminanceInfluence,min:0,max:1,step:.01,onChange:n=>t("ssao",{...o,luminanceInfluence:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.fade",label:"Fade",value:o.fade,min:0,max:.1,step:.001,onChange:n=>t("ssao",{...o,fade:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.minRadiusScale",label:"Min radius scale",value:o.minRadiusScale,min:0,max:1,step:.01,onChange:n=>t("ssao",{...o,minRadiusScale:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.worldDistanceThreshold",label:"World distance threshold",value:o.worldDistanceThreshold,min:0,max:100,step:.1,onChange:n=>t("ssao",{...o,worldDistanceThreshold:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.worldDistanceFalloff",label:"World distance falloff",value:o.worldDistanceFalloff,min:0,max:20,step:.1,onChange:n=>t("ssao",{...o,worldDistanceFalloff:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.worldProximityThreshold",label:"World proximity threshold",value:o.worldProximityThreshold,min:0,max:100,step:.1,onChange:n=>t("ssao",{...o,worldProximityThreshold:n})}),Y(O,{path:"sceneConfig.postProcessing.ssao.worldProximityFalloff",label:"World proximity falloff",value:o.worldProximityFalloff,min:0,max:20,step:.1,onChange:n=>t("ssao",{...o,worldProximityFalloff:n})})]})}function yc({pp:e,set:t,open:i,toggle:a}){let{autofocus:o}=e;return oi(oe,{title:"Auto focus",tooltip:"Keeps the focus plane tracking a subject so the image stays sharp where you want it.",open:i.autofocus,onToggle:()=>a("autofocus"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("autofocus",{...o,enabled:n}),label:"Toggle autofocus"}),children:[Y(O,{path:"sceneConfig.postProcessing.autofocus.focusDistance",label:"Focus distance",value:o.focusDistance,min:0,max:50,step:.1,onChange:n=>t("autofocus",{...o,focusDistance:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.focusRange",label:"Focus range",value:o.focusRange,min:.1,max:50,step:.1,onChange:n=>t("autofocus",{...o,focusRange:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.focalLength",label:"Focal length",value:o.focalLength,min:0,max:1,step:.01,onChange:n=>t("autofocus",{...o,focalLength:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.bokehScale",label:"Bokeh scale",value:o.bokehScale,min:0,max:20,step:.1,onChange:n=>t("autofocus",{...o,bokehScale:n})}),Y(kt,{path:"sceneConfig.postProcessing.autofocus.target",label:"Target",value:o.target,min:-100,max:100,step:.1,onChange:n=>t("autofocus",{...o,target:n})}),Y(be,{path:"sceneConfig.postProcessing.autofocus.mouse",label:"Mouse follow",checked:o.mouse,onChange:n=>t("autofocus",{...o,mouse:n})}),Y(be,{path:"sceneConfig.postProcessing.autofocus.manual",label:"Manual update",checked:o.manual,onChange:n=>t("autofocus",{...o,manual:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.debug",label:"Debug",value:o.debug,min:0,max:1,step:.01,onChange:n=>t("autofocus",{...o,debug:n})}),Y(O,{path:"sceneConfig.postProcessing.autofocus.smoothTime",label:"Smooth time",value:o.smoothTime,min:0,max:2,step:.01,onChange:n=>t("autofocus",{...o,smoothTime:n})})]})}function wc({pp:e,set:t,open:i,toggle:a}){let{godRays:o}=e;return oi(oe,{title:"God rays",tooltip:"Creates light shafts that streak outward from a bright sun or light source.",open:i.godRays,onToggle:()=>a("godRays"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("godRays",{...o,enabled:n}),label:"Toggle god rays"}),children:[Y(kt,{path:"sceneConfig.postProcessing.godRays.sunPosition",label:"Sun position",value:o.sunPosition,min:-100,max:100,step:.1,onChange:n=>t("godRays",{...o,sunPosition:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.samples",label:"Samples",value:o.samples,min:1,max:128,step:1,onChange:n=>t("godRays",{...o,samples:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.density",label:"Density",value:o.density,min:0,max:2,step:.01,onChange:n=>t("godRays",{...o,density:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.decay",label:"Decay",value:o.decay,min:0,max:1,step:.01,onChange:n=>t("godRays",{...o,decay:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.weight",label:"Weight",value:o.weight,min:0,max:2,step:.01,onChange:n=>t("godRays",{...o,weight:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.exposure",label:"Exposure",value:o.exposure,min:0,max:2,step:.01,onChange:n=>t("godRays",{...o,exposure:n})}),Y(O,{path:"sceneConfig.postProcessing.godRays.clampMax",label:"Clamp max",value:o.clampMax,min:0,max:2,step:.01,onChange:n=>t("godRays",{...o,clampMax:n})}),Y(be,{path:"sceneConfig.postProcessing.godRays.blur",label:"Blur",checked:o.blur,onChange:n=>t("godRays",{...o,blur:n})}),Y(st,{path:"sceneConfig.postProcessing.godRays.kernelSize",label:"Kernel size",value:o.kernelSize,options:Wn,onChange:n=>t("godRays",{...o,kernelSize:n})})]})}function Sc({pp:e,set:t,open:i,toggle:a}){let{lensflare:o}=e;return oi(oe,{title:"Lens flare",tooltip:"Adds camera flare artifacts and glow from a bright light source.",open:i.lensflare,onToggle:()=>a("lensflare"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("lensflare",{...o,enabled:n}),label:"Toggle lensflare"}),children:[Y(kt,{path:"sceneConfig.postProcessing.lensflare.lensPosition",label:"Lens position",value:o.lensPosition,min:-100,max:100,step:.1,onChange:n=>t("lensflare",{...o,lensPosition:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.smoothTime",label:"Smooth time",value:o.smoothTime,min:0,max:1,step:.01,onChange:n=>t("lensflare",{...o,smoothTime:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.glareSize",label:"Glare size",value:o.glareSize,min:0,max:1,step:.01,onChange:n=>t("lensflare",{...o,glareSize:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.flareSize",label:"Flare size",value:o.flareSize,min:0,max:.1,step:.001,onChange:n=>t("lensflare",{...o,flareSize:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.flareSpeed",label:"Flare speed",value:o.flareSpeed,min:0,max:.2,step:.001,onChange:n=>t("lensflare",{...o,flareSpeed:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.flareShape",label:"Flare shape",value:o.flareShape,min:0,max:.2,step:.001,onChange:n=>t("lensflare",{...o,flareShape:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.animated",label:"Animated",checked:o.animated,onChange:n=>t("lensflare",{...o,animated:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.anamorphic",label:"Anamorphic",checked:o.anamorphic,onChange:n=>t("lensflare",{...o,anamorphic:n})}),Y(pt,{path:"sceneConfig.postProcessing.lensflare.colorGain",label:"Color gain",value:o.colorGain,onChange:n=>t("lensflare",{...o,colorGain:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.haloScale",label:"Halo scale",value:o.haloScale,min:0,max:2,step:.01,onChange:n=>t("lensflare",{...o,haloScale:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.secondaryGhosts",label:"Secondary ghosts",checked:o.secondaryGhosts,onChange:n=>t("lensflare",{...o,secondaryGhosts:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.aditionalStreaks",label:"Additional streaks",checked:o.aditionalStreaks,onChange:n=>t("lensflare",{...o,aditionalStreaks:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.ghostScale",label:"Ghost scale",value:o.ghostScale,min:0,max:1,step:.01,onChange:n=>t("lensflare",{...o,ghostScale:n})}),Y(O,{path:"sceneConfig.postProcessing.lensflare.opacity",label:"Opacity",value:o.opacity,min:0,max:1,step:.01,onChange:n=>t("lensflare",{...o,opacity:n})}),Y(be,{path:"sceneConfig.postProcessing.lensflare.starBurst",label:"Star burst",checked:o.starBurst,onChange:n=>t("lensflare",{...o,starBurst:n})})]})}function kc({pp:e,set:t,open:i,toggle:a}){let{depthOfField:o}=e;return oi(oe,{title:"Depth of field",tooltip:"Blurs areas that sit away from the focal plane for a camera-like look.",open:i.depthOfField,onToggle:()=>a("depthOfField"),disabled:!o.enabled,trailing:Y(se,{checked:o.enabled,onChange:n=>t("depthOfField",{...o,enabled:n}),label:"Toggle depth of field"}),children:[Y(O,{path:"sceneConfig.postProcessing.depthOfField.focusDistance",label:"Focus distance",value:o.focusDistance,min:0,max:50,step:.1,onChange:n=>t("depthOfField",{...o,focusDistance:n})}),Y(O,{path:"sceneConfig.postProcessing.depthOfField.focusRange",label:"Focus range",value:o.focusRange,min:.1,max:50,step:.1,onChange:n=>t("depthOfField",{...o,focusRange:n})}),Y(O,{path:"sceneConfig.postProcessing.depthOfField.focalLength",label:"Focal length",value:o.focalLength,min:0,max:1,step:.01,onChange:n=>t("depthOfField",{...o,focalLength:n})}),Y(O,{path:"sceneConfig.postProcessing.depthOfField.bokehScale",label:"Bokeh scale",value:o.bokehScale,min:0,max:20,step:.1,onChange:n=>t("depthOfField",{...o,bokehScale:n})})]})}import{jsx as re,jsxs as Mn}from"react/jsx-runtime";function Cc({pp:e,set:t,open:i,toggle:a}){let{dotScreen:o}=e;return Mn(oe,{title:"Dot screen",tooltip:"Overlays a halftone dot pattern for a printed or retro look.",open:i.dotScreen,onToggle:()=>a("dotScreen"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("dotScreen",{...o,enabled:n}),label:"Toggle dot screen"}),children:[re(O,{path:"sceneConfig.postProcessing.dotScreen.angle",label:"Angle",value:o.angle,min:0,max:Math.PI*2,step:.01,formatValue:n=>`${n.toFixed(2)} rad`,onChange:n=>t("dotScreen",{...o,angle:n})}),re(O,{path:"sceneConfig.postProcessing.dotScreen.scale",label:"Scale",value:o.scale,min:.1,max:10,step:.05,onChange:n=>t("dotScreen",{...o,scale:n})})]})}function Mc({pp:e,set:t,open:i,toggle:a}){let{glitch:o}=e;return Mn(oe,{title:"Glitch",tooltip:"Introduces digital distortion, tearing, and scan noise.",open:i.glitch,onToggle:()=>a("glitch"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("glitch",{...o,enabled:n}),label:"Toggle glitch"}),children:[re(st,{path:"sceneConfig.postProcessing.glitch.mode",label:"Mode",value:o.mode,options:jl,onChange:n=>t("glitch",{...o,mode:n})}),re($o,{path:"sceneConfig.postProcessing.glitch.delay",label:"Delay",value:o.delay,min:0,max:10,step:.01,onChange:n=>t("glitch",{...o,delay:n})}),re($o,{path:"sceneConfig.postProcessing.glitch.duration",label:"Duration",value:o.duration,min:0,max:5,step:.01,onChange:n=>t("glitch",{...o,duration:n})}),re($o,{path:"sceneConfig.postProcessing.glitch.strength",label:"Strength",value:o.strength,min:0,max:2,step:.01,onChange:n=>t("glitch",{...o,strength:n})}),re($o,{path:"sceneConfig.postProcessing.glitch.chromaticAberrationOffset",label:"Chromatic aberration offset",value:o.chromaticAberrationOffset,min:0,max:.02,step:1e-4,onChange:n=>t("glitch",{...o,chromaticAberrationOffset:n})}),re(O,{path:"sceneConfig.postProcessing.glitch.columns",label:"Columns",value:o.columns,min:0,max:.5,step:.001,onChange:n=>t("glitch",{...o,columns:n})}),re(O,{path:"sceneConfig.postProcessing.glitch.ratio",label:"Ratio",value:o.ratio,min:0,max:1,step:.01,onChange:n=>t("glitch",{...o,ratio:n})})]})}function Pc({pp:e,set:t,open:i,toggle:a}){let{grid:o}=e;return Mn(oe,{title:"Grid",tooltip:"Adds a visual grid overlay that feels retro or debug-like.",open:i.grid,onToggle:()=>a("grid"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("grid",{...o,enabled:n}),label:"Toggle grid"}),children:[re(O,{path:"sceneConfig.postProcessing.grid.scale",label:"Scale",value:o.scale,min:.1,max:10,step:.05,onChange:n=>t("grid",{...o,scale:n})}),re(O,{path:"sceneConfig.postProcessing.grid.lineWidth",label:"Line width",value:o.lineWidth,min:0,max:1,step:.01,onChange:n=>t("grid",{...o,lineWidth:n})})]})}function Bc({pp:e,set:t,open:i,toggle:a}){let{chromaticAberration:o}=e;return Mn(oe,{title:"Chromatic aberration",tooltip:"Separates color channels slightly to mimic lens fringing.",open:i.chromaticAberration,onToggle:()=>a("chromaticAberration"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("chromaticAberration",{...o,enabled:n}),label:"Toggle chromatic aberration"}),children:[re(O,{path:"sceneConfig.postProcessing.chromaticAberration.offsetX",label:"Offset X",value:o.offsetX,min:0,max:.02,step:1e-4,onChange:n=>t("chromaticAberration",{...o,offsetX:n})}),re(O,{path:"sceneConfig.postProcessing.chromaticAberration.offsetY",label:"Offset Y",value:o.offsetY,min:0,max:.02,step:1e-4,onChange:n=>t("chromaticAberration",{...o,offsetY:n})}),re(be,{path:"sceneConfig.postProcessing.chromaticAberration.radialModulation",label:"Radial modulation",checked:o.radialModulation,onChange:n=>t("chromaticAberration",{...o,radialModulation:n})}),re(O,{path:"sceneConfig.postProcessing.chromaticAberration.modulationOffset",label:"Modulation offset",value:o.modulationOffset,min:0,max:1,step:.01,onChange:n=>t("chromaticAberration",{...o,modulationOffset:n})})]})}function Tc({pp:e,set:t,open:i,toggle:a}){let{noise:o}=e;return Mn(oe,{title:"Noise",tooltip:"Adds film grain or static noise to the rendered image.",open:i.noise,onToggle:()=>a("noise"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("noise",{...o,enabled:n}),label:"Toggle noise"}),children:[re(O,{path:"sceneConfig.postProcessing.noise.opacity",label:"Amount",value:o.opacity,min:0,max:1,step:.01,onChange:n=>t("noise",{...o,opacity:n})}),re(be,{path:"sceneConfig.postProcessing.noise.premultiply",label:"Premultiply",checked:o.premultiply,onChange:n=>t("noise",{...o,premultiply:n})})]})}function Rc({pp:e,set:t,open:i,toggle:a}){let{scanline:o}=e;return re(oe,{title:"Scan lines",tooltip:"Draws horizontal CRT-style scan lines over the frame.",open:i.scanline,onToggle:()=>a("scanline"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("scanline",{...o,enabled:n}),label:"Toggle scanline"}),children:re(O,{path:"sceneConfig.postProcessing.scanline.density",label:"Density",value:o.density,min:0,max:10,step:.25,onChange:n=>t("scanline",{...o,density:n})})})}function Nc({pp:e,set:t,open:i,toggle:a}){let{pixelation:o}=e;return re(oe,{title:"Pixelation",tooltip:"Reduces detail into larger pixels for a blocky stylized effect.",open:i.pixelation,onToggle:()=>a("pixelation"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("pixelation",{...o,enabled:n}),label:"Toggle pixelation"}),children:re(O,{path:"sceneConfig.postProcessing.pixelation.granularity",label:"Granularity",value:o.granularity,min:0,max:20,step:1,onChange:n=>t("pixelation",{...o,granularity:n})})})}function Ac({pp:e,set:t,open:i,toggle:a}){let{ramp:o}=e;return Mn(oe,{title:"Color ramp",tooltip:"Adds a screen-space color gradient, or masks effects earlier in the stack.",open:i.ramp,onToggle:()=>a("ramp"),disabled:!o.enabled,trailing:re(se,{checked:o.enabled,onChange:n=>t("ramp",{...o,enabled:n}),label:"Toggle ramp"}),children:[re(st,{path:"sceneConfig.postProcessing.ramp.rampType",label:"Ramp type",value:o.rampType,options:Il,onChange:n=>t("ramp",{...o,rampType:n})}),re($o,{path:"sceneConfig.postProcessing.ramp.rampStart",label:"Ramp start",value:o.rampStart,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,rampStart:n})}),re($o,{path:"sceneConfig.postProcessing.ramp.rampEnd",label:"Ramp end",value:o.rampEnd,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,rampEnd:n})}),re(pt,{path:"sceneConfig.postProcessing.ramp.startColor",label:"Start color",value:o.startColor,onChange:n=>t("ramp",{...o,startColor:n})}),re(pt,{path:"sceneConfig.postProcessing.ramp.endColor",label:"End color",value:o.endColor,onChange:n=>t("ramp",{...o,endColor:n})}),!o.rampMask&&re(O,{path:"sceneConfig.postProcessing.ramp.opacity",label:"Gradient opacity",value:o.opacity??.5,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,opacity:n})}),re(O,{path:"sceneConfig.postProcessing.ramp.rampBias",label:"Bias",value:o.rampBias,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,rampBias:n})}),re(O,{path:"sceneConfig.postProcessing.ramp.rampGain",label:"Gain",value:o.rampGain,min:0,max:1,step:.01,onChange:n=>t("ramp",{...o,rampGain:n})}),re(be,{path:"sceneConfig.postProcessing.ramp.rampMask",label:"Mask earlier effects",checked:o.rampMask,onChange:n=>t("ramp",{...o,rampMask:n})}),re(be,{path:"sceneConfig.postProcessing.ramp.rampInvert",label:"Invert",checked:o.rampInvert,onChange:n=>t("ramp",{...o,rampInvert:n})})]})}import{jsx as Te,jsxs as Ic}from"react/jsx-runtime";function Oc({pp:e,set:t,open:i,toggle:a}){let{outline:o}=e;return Ic(oe,{title:"Outline",tooltip:"Draws a visible edge around the selected object binding.",open:i.outline,onToggle:()=>a("outline"),disabled:!o.enabled,trailing:Te(se,{checked:o.enabled,onChange:n=>t("outline",{...o,enabled:n}),label:"Toggle outline"}),children:[Te("div",{className:"se-placeholder",children:"Outlines the currently selected object binding in the model editor."}),Te(O,{path:"sceneConfig.postProcessing.outline.selectionLayer",label:"Selection layer",value:o.selectionLayer,min:0,max:20,step:1,onChange:n=>t("outline",{...o,selectionLayer:n})}),Te(O,{path:"sceneConfig.postProcessing.outline.edgeStrength",label:"Edge strength",value:o.edgeStrength,min:0,max:10,step:.1,onChange:n=>t("outline",{...o,edgeStrength:n})}),Te(O,{path:"sceneConfig.postProcessing.outline.pulseSpeed",label:"Pulse speed",value:o.pulseSpeed,min:0,max:10,step:.1,onChange:n=>t("outline",{...o,pulseSpeed:n})}),Te(pt,{path:"sceneConfig.postProcessing.outline.visibleEdgeColor",label:"Visible edge color",value:o.visibleEdgeColor,onChange:n=>t("outline",{...o,visibleEdgeColor:n})}),Te(pt,{path:"sceneConfig.postProcessing.outline.hiddenEdgeColor",label:"Hidden edge color",value:o.hiddenEdgeColor,onChange:n=>t("outline",{...o,hiddenEdgeColor:n})}),Te(st,{path:"sceneConfig.postProcessing.outline.kernelSize",label:"Kernel size",value:o.kernelSize,options:Wn,onChange:n=>t("outline",{...o,kernelSize:n})}),Te(be,{path:"sceneConfig.postProcessing.outline.blur",label:"Blur",checked:o.blur,onChange:n=>t("outline",{...o,blur:n})}),Te(be,{path:"sceneConfig.postProcessing.outline.xRay",label:"X-Ray",checked:o.xRay,onChange:n=>t("outline",{...o,xRay:n})})]})}function Ec({pp:e,set:t,open:i,toggle:a}){let{selectiveBloom:o}=e;return Ic(oe,{title:"Selective bloom",tooltip:"Applies bloom only to objects assigned to the selected layer.",open:i.selectiveBloom,onToggle:()=>a("selectiveBloom"),disabled:!o.enabled,trailing:Te(se,{checked:o.enabled,onChange:n=>t("selectiveBloom",{...o,enabled:n}),label:"Toggle selective bloom"}),children:[Te("div",{className:"se-placeholder",children:"Applies bloom to the currently selected object binding."}),Te(O,{path:"sceneConfig.postProcessing.selectiveBloom.selectionLayer",label:"Selection layer",value:o.selectionLayer,min:0,max:20,step:1,onChange:n=>t("selectiveBloom",{...o,selectionLayer:n})}),Te(O,{path:"sceneConfig.postProcessing.selectiveBloom.intensity",label:"Intensity",value:o.intensity,min:0,max:5,step:.05,onChange:n=>t("selectiveBloom",{...o,intensity:n})}),Te(O,{path:"sceneConfig.postProcessing.selectiveBloom.luminanceThreshold",label:"Threshold",value:o.luminanceThreshold,min:0,max:1,step:.01,onChange:n=>t("selectiveBloom",{...o,luminanceThreshold:n})}),Te(O,{path:"sceneConfig.postProcessing.selectiveBloom.luminanceSmoothing",label:"Smoothing",value:o.luminanceSmoothing,min:0,max:1,step:.01,onChange:n=>t("selectiveBloom",{...o,luminanceSmoothing:n})}),Te(st,{path:"sceneConfig.postProcessing.selectiveBloom.kernelSize",label:"Kernel size",value:o.kernelSize,options:Wn,onChange:n=>t("selectiveBloom",{...o,kernelSize:n})}),Te(be,{path:"sceneConfig.postProcessing.selectiveBloom.mipmapBlur",label:"Mipmap blur",checked:o.mipmapBlur,onChange:n=>t("selectiveBloom",{...o,mipmapBlur:n})}),Te(be,{path:"sceneConfig.postProcessing.selectiveBloom.inverted",label:"Inverted",checked:o.inverted,onChange:n=>t("selectiveBloom",{...o,inverted:n})}),Te(be,{path:"sceneConfig.postProcessing.selectiveBloom.ignoreBackground",label:"Ignore background",checked:o.ignoreBackground,onChange:n=>t("selectiveBloom",{...o,ignoreBackground:n})})]})}function jc({pp:e,set:t,open:i,toggle:a}){let{smaa:o}=e;return Te(oe,{title:"Anti-aliasing",tooltip:"Reduces jagged edges with subpixel anti-aliasing.",open:i.smaa,onToggle:()=>a("smaa"),trailing:Te(se,{checked:o.enabled,onChange:n=>t("smaa",{...o,enabled:n}),label:"Toggle smaa"}),children:Te("div",{className:"se-placeholder",children:"Subpixel Morphological Anti-Aliasing smooths jagged edges in post-process."})})}import{jsx as _t,jsxs as ni}from"react/jsx-runtime";var zc=[{key:"toneMapping",label:"Tone mapping",group:"Color",Section:hc},{key:"brightnessContrast",label:"Brightness and contrast",group:"Color",Section:bc},{key:"hueSaturation",label:"Hue and saturation",group:"Color",Section:gc},{key:"colorAverage",label:"Color average",group:"Color",Section:uc},{key:"sepia",label:"Sepia",group:"Color",Section:xc},{key:"vignette",label:"Vignette",group:"Color",Section:mc},{key:"bloom",label:"Bloom",group:"Lighting",Section:fc},{key:"ssao",label:"Ambient occlusion",hint:"SSAO",group:"Lighting",feature:"postLighting",Section:vc},{key:"depthOfField",label:"Depth of field",group:"Lighting",feature:"postLighting",Section:kc},{key:"autofocus",label:"Auto focus",group:"Lighting",feature:"postLighting",Section:yc},{key:"godRays",label:"God rays",group:"Lighting",feature:"postLighting",Section:wc},{key:"lensflare",label:"Lens flare",group:"Lighting",feature:"postLighting",Section:Sc},{key:"outline",label:"Outline",group:"Selection",feature:"postSelection",Section:Oc},{key:"selectiveBloom",label:"Selective bloom",group:"Selection",feature:"postSelection",Section:Ec},{key:"smaa",label:"Anti-aliasing",hint:"SMAA",group:"Selection",feature:"postSelection",Section:jc},{key:"chromaticAberration",label:"Chromatic aberration",group:"Stylize",feature:"postSelection",Section:Bc},{key:"dotScreen",label:"Dot screen",group:"Stylize",feature:"postSelection",Section:Cc},{key:"glitch",label:"Glitch",group:"Stylize",feature:"postSelection",Section:Mc},{key:"grid",label:"Grid",group:"Stylize",feature:"postSelection",Section:Pc},{key:"noise",label:"Noise",group:"Stylize",feature:"postSelection",Section:Tc},{key:"pixelation",label:"Pixelation",group:"Stylize",feature:"postSelection",Section:Nc},{key:"ramp",label:"Color ramp",group:"Stylize",feature:"postSelection",Section:Ac},{key:"scanline",label:"Scan lines",group:"Stylize",feature:"postSelection",Section:Rc}],zm=["Color","Lighting","Selection","Stylize"],Lm={postLighting:"starter",postSelection:"growth"};function Ba({config:e,onChange:t}){let[i,a]=rr({}),[o,n]=rr(()=>new Set),[d,s]=rr(!1),[p,c]=rr(null),x=Em(null);hn([x],()=>s(!1),d),Om(()=>{if(!d)return;let m=N=>{N.key==="Escape"&&s(!1)};return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[d]);let h=m=>a(N=>({...N,[m]:!N[m]})),{tier:g}=it(),C=e.postProcessing,M=(m,N)=>t({...e,postProcessing:{...C,[m]:N}}),y=m=>!m.feature||nt(g,m.feature),T=zc.filter(m=>y(m)&&(C[m.key]?.enabled===!0||o.has(m.key))),f=zc.filter(m=>!T.includes(m)),u={pp:C,set:M,open:i,toggle:h},v=m=>{if(s(!1),!y(m)){c(m);return}c(null),n(N=>new Set(N).add(m.key)),a(N=>({...N,[m.key]:!0})),M(m.key,{...C[m.key],enabled:!0})};return ni("div",{className:"se-generalContent",children:[ni("div",{className:"se-listHeader",ref:x,children:[_t("span",{children:"Effects"}),ni("button",{type:"button",className:"bb-button bb-button--ghost bb-button--small","aria-expanded":d,disabled:!f.length,onClick:()=>s(m=>!m),children:[_t(Im,{size:13,"aria-hidden":"true"}),"Add effect"]}),d?_t("div",{className:"se-addMenu",role:"menu","aria-label":"Add effect",children:zm.map(m=>{let N=f.filter(A=>A.group===m);return N.length?ni("div",{role:"group","aria-label":m,children:[_t("h6",{children:m}),N.map(A=>ni("button",{type:"button",role:"menuitem",onClick:()=>v(A),children:[_t("span",{children:A.label}),A.hint?_t("small",{children:A.hint}):null,y(A)?null:_t(jm,{size:12,"aria-label":"Needs an upgrade"})]},A.key))]},m):null})}):null]}),p?.feature?_t(We,{requiredTier:Lm[p.feature],feature:p.label}):null,T.length?null:_t("p",{className:"se-listEmpty",children:"Add an effect to shape the final image, starting with tone mapping or bloom."}),T.map(({key:m,Section:N})=>_t(N,{...u},m))]})}import{useState as Lc,useSyncExternalStore as Dm}from"react";import{Eye as Fm,EyeOff as Hm,Plus as $m,Trash2 as Um}from"lucide-react";import{Fragment as Gm,jsx as xe,jsxs as ro}from"react/jsx-runtime";var _m=["512","1024","2048","4096"],Dc={none:"None",directional:"Directional",point:"Point",spot:"Spot",hemisphere:"Hemisphere"};function Vm({index:e,light:t,selected:i,onSelect:a,onToggleVisible:o}){return ro("div",{className:`se-lightRow ${i?"se-lightRow--active":""}`,onClick:a,children:[ro("span",{className:"se-lightRowLabel",children:[e+1,": ",Dc[t.type]]}),xe("button",{type:"button",className:"se-iconButton","aria-label":t.visible?"Hide light":"Show light",onClick:n=>{n.stopPropagation(),o()},children:t.visible?xe(Fm,{size:14}):xe(Hm,{size:14})})]})}function Km(){return{id:crypto.randomUUID(),type:"directional",color:"#ffffff",intensity:1,position:[5,10,5],attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0}}function Ta({config:e,onChange:t}){let[i,a]=Lc({lights:!0,shadows:!1,groundShadows:!1,environment:!1,envShadow:!1}),o=Dm(ld,dd),[n,d]=Lc(e.lighting.lights[0]?.id??null),s=o??n,p=B=>{d(B),sd(B)},c=B=>a(P=>({...P,[B]:!P[B]})),{tier:x}=it(),{lighting:h,shadows:g,groundShadows:C,environment:M}=e,y=B=>t({...e,lighting:B}),T=B=>t({...e,shadows:B}),f=B=>t({...e,groundShadows:B}),u=B=>t({...e,environment:B}),v=(B,P)=>{y({...h,lights:h.lights.map($=>$.id===B?{...$,...P}:$)})},m=h.lights.find(B=>B.id===s)??null,N=()=>{let B=Km();y({...h,lights:[...h.lights,B]}),p(B.id)},A=()=>{if(!m)return;let B=h.lights.filter(P=>P.id!==m.id);y({...h,lights:B}),p(B[0]?.id??null)},G=St(x,"lights",h.lights.length);return ro("div",{className:"se-generalContent",children:[ro(oe,{title:"Lights",open:i.lights,onToggle:()=>c("lights"),trailing:ro("span",{className:"se-listHeaderActions",children:[m&&h.lights.length>1?xe("button",{type:"button",className:"se-iconButton",onClick:A,title:"Remove selected light","aria-label":"Remove selected light",children:xe(Um,{size:13})}):null,xe("button",{type:"button",className:"se-iconButton",onClick:N,disabled:!G,title:"Add light","aria-label":"Add light",children:xe($m,{size:14})})]}),children:[xe("div",{className:"se-lightList",children:h.lights.map((B,P)=>xe(Vm,{index:P,light:B,selected:B.id===s,onSelect:()=>p(B.id),onToggleVisible:()=>v(B.id,{visible:!B.visible})},B.id))}),G?null:xe(We,{requiredTier:Ho("lights",h.lights.length),feature:"More lights"}),m?ro("div",{className:"se-lightProps",children:[ro("div",{className:"se-field se-fieldInline","data-ri-path":"sceneConfig.lighting.lights[\u2026].type",children:[xe("span",{className:"se-fieldLabel",children:"Type"}),xe("select",{className:"se-select",value:m.type,onChange:B=>v(m.id,{type:B.target.value}),children:Al.map(B=>xe("option",{value:B,children:Dc[B]},B))})]}),xe(pt,{path:"sceneConfig.lighting.lights[\u2026].color",label:"Color",value:m.color,onChange:B=>v(m.id,{color:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].intensity",label:"Intensity",value:m.intensity,min:0,max:10,step:.1,onChange:B=>v(m.id,{intensity:B})}),m.type!=="hemisphere"&&m.type!=="none"&&xe(kt,{path:"sceneConfig.lighting.lights[\u2026].position",label:"Position",value:m.position,min:-100,max:100,step:.05,onChange:B=>v(m.id,{position:B})}),m.type==="spot"&&ro(Gm,{children:[xe(O,{path:"sceneConfig.lighting.lights[\u2026].angle",label:"Angle",value:m.angle??Math.PI/6,min:0,max:Math.PI/2,step:.01,formatValue:B=>`${Math.round(B*180/Math.PI)}\xB0`,onChange:B=>v(m.id,{angle:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].penumbra",label:"Penumbra",value:m.penumbra??.2,min:0,max:1,step:.01,onChange:B=>v(m.id,{penumbra:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].distance",label:"Distance",value:m.distance??0,min:0,max:100,step:.5,onChange:B=>v(m.id,{distance:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].decay",label:"Decay",value:m.decay??2,min:0,max:4,step:.1,onChange:B=>v(m.id,{decay:B})})]}),xe(be,{path:"sceneConfig.lighting.lights[\u2026].attachedToCamera",label:"Attached to camera",checked:m.attachedToCamera,onChange:B=>v(m.id,{attachedToCamera:B})}),xe(be,{path:"sceneConfig.lighting.lights[\u2026].castShadow",label:"Cast shadows",checked:m.castShadow,onChange:B=>v(m.id,{castShadow:B})}),xe(O,{path:"sceneConfig.lighting.lights[\u2026].shadowBias",label:"Shadow bias",value:m.shadowBias,min:-.01,max:.01,step:1e-4,onChange:B=>v(m.id,{shadowBias:B})})]}):null]}),ro(oe,{title:"Shadows",open:i.shadows,onToggle:()=>c("shadows"),disabled:!g.enabled,trailing:xe(se,{checked:g.enabled,onChange:B=>T({...g,enabled:B}),label:"Toggle shadows"}),children:[xe(st,{label:"Map size",value:String(g.mapSize),options:_m,onChange:B=>T({...g,mapSize:Number(B)})}),xe(O,{path:"sceneConfig.shadows.bias",label:"Bias",value:g.bias,min:-.01,max:.01,step:1e-4,onChange:B=>T({...g,bias:B})}),xe(O,{path:"sceneConfig.shadows.normalBias",label:"Normal bias",value:g.normalBias,min:0,max:.2,step:.01,onChange:B=>T({...g,normalBias:B})}),xe(O,{path:"sceneConfig.shadows.radius",label:"Radius (softness)",value:g.radius,min:0,max:20,step:.5,onChange:B=>T({...g,radius:B})})]})]})}import{lazy as qm,Suspense as Wm}from"react";import{jsx as Ra}from"react/jsx-runtime";function ko(e){let t=qm(e);return function(a){return Ra(Wm,{fallback:Ra("p",{className:"bb-panelEmpty",children:"Loading\u2026"}),children:Ra(t,{...a})})}}import{jsx as Ko,jsxs as Zm}from"react/jsx-runtime";var Ym=ko(()=>import("./RulesTab-YVBZGJZX.mjs")),Fc=[{id:"model",label:"Model"},{id:"camera",label:"Camera"},{id:"world",label:"World"},{id:"lighting",label:"Lights"},{id:"postProcessing",label:"Effects"},{id:"rules",label:"Rules"}],Jm=[],Xm={};function Na({diagnostics:e,onDiagnosticsOpenChange:t,config:i,onChange:a,activeSubTab:o,materialVariantGroups:n=Jm,onImageFile:d,objectBindings:s=Xm}){let{tier:p}=it();return Zm("div",{className:"se-tabContent",children:[o==="model"&&Ko(dc,{diagnostics:e,onDiagnosticsOpenChange:t,config:i,onChange:a,materialVariantGroups:n}),o==="camera"&&Ko(cc,{config:i,onChange:a}),o==="world"&&Ko(pc,{config:i,onChange:a,onImageFile:d}),o==="lighting"&&Ko(Ta,{config:i,onChange:a}),o==="postProcessing"&&Ko(Ba,{config:i,onChange:a}),o==="rules"&&(nt(p,"rules")?Ko(Ym,{config:i,onChange:a,objectBindings:s}):Ko(We,{requiredTier:"growth",feature:"Rules"}))]})}import{ChevronRight as Hc,Info as $c}from"lucide-react";import{jsx as Vt,jsxs as Pn}from"react/jsx-runtime";function Uc({title:e,trailing:t,children:i,disabled:a,open:o,onToggle:n,tooltip:d}){return Pn("div",{className:"bb-materialPanel","data-ri-section":e,children:[Pn("div",{className:"bb-materialPanelHeaderRow",children:[Pn("button",{type:"button",className:"bb-materialPanelHeader",onClick:n,"aria-expanded":o,title:d,children:[Vt(Hc,{size:13,className:`bb-materialPanelChevron ${o?"bb-materialPanelChevron--open":""}`}),Vt("span",{className:"bb-materialPanelTitle",children:e}),d?Vt($c,{size:11,className:"bb-materialPanelHelp","aria-hidden":"true"}):null]}),t?Vt("span",{className:"bb-materialPanelTrailing",children:t}):null]}),o?Vt("div",{className:`bb-materialPanelBody ${a?"bb-materialPanelBody--disabled":""}`,children:i}):null]})}function Ye({title:e,open:t,onToggle:i,trailing:a,children:o,tooltip:n}){return Pn("div",{className:"bb-section","data-ri-section":e,children:[Pn("div",{className:"bb-sectionHeaderRow",children:[Pn("button",{type:"button",className:"bb-sectionHeaderButton",onClick:i,"aria-expanded":t,title:n,children:[Vt(Hc,{size:13,className:`bb-sectionChevron ${t?"bb-sectionChevron--open":""}`}),Vt("h2",{className:"bb-sectionTitle",children:e}),n?Vt($c,{size:11,className:"bb-sectionHelp","aria-hidden":"true"}):null]}),a?Vt("span",{className:"bb-sectionHeaderTrailing",children:a}):null]}),t?Vt("div",{className:"bb-sectionBody",children:o}):null]})}import{Copy as Qm,Plus as ef,Scan as tf,Trash2 as of}from"lucide-react";import{Fragment as nf,jsx as Re,jsxs as Kt}from"react/jsx-runtime";function Aa(e){let t=e.assets.find(o=>o.url===e.activeUrl),i=t?.placement??{},a=e.assets.length<2?"Use Remove model to clear the last model":e.deleteIsPermanent?"Delete model":"Delete model (undoable)";return Kt("div",{className:"ri-assets",children:[Kt(Pd,{title:"Models",children:[Re("button",{type:"button",className:"se-iconButton",title:"Frame all models","aria-label":"Frame all models",onClick:e.onFrameAll,children:Re(tf,{size:13})}),Re("button",{type:"button",className:"se-iconButton",title:"Add model","aria-label":"Add model",disabled:e.busy||!!e.addRequiresTier,onClick:e.onAdd,children:Re(ef,{size:14})})]}),e.addRequiresTier?Re(We,{requiredTier:e.addRequiresTier,feature:"More models in a project"}):null,Re("ul",{className:"ri-assets-list","aria-label":"Models in this scene",children:e.assets.map(o=>Re("li",{children:Kt("button",{type:"button",className:o.url===e.activeUrl?"ri-assets-item is-active":"ri-assets-item","aria-pressed":o.url===e.activeUrl,onClick:()=>e.onSelect(o.url),children:[Re("span",{className:"ri-assets-itemName",children:o.displayName??o.placement.label??o.name}),Re("small",{children:o.placement.visible===!1?"Hidden":o.ready?null:"Loading"})]})},o.id))}),t&&Kt(nf,{children:[Kt(ma,{title:"Placement",children:[Re(xn,{label:"Name",children:Re("input",{className:"se-textInput","aria-label":"Model name",value:i.label??t.name,maxLength:512,onChange:o=>e.onChange(t.id,{label:o.target.value})})}),Re(be,{label:"Visible",checked:i.visible!==!1,onChange:o=>e.onChange(t.id,{visible:o})}),Re(kt,{min:-1e6,max:1e6,label:"Position",value:i.position??[0,0,0],step:.1,onChange:o=>e.onChange(t.id,{position:o})}),Re(kt,{min:-1e6,max:1e6,label:"Rotation",value:(i.rotation??[0,0,0]).map(o=>o*180/Math.PI),step:1,onChange:o=>e.onChange(t.id,{rotation:o.map(n=>n*Math.PI/180)})}),Re(kt,{min:-1e6,max:1e6,label:"Scale",value:i.scale??[1,1,1],step:.1,onChange:o=>{o.every(n=>n!==0)&&e.onChange(t.id,{scale:o})}})]}),Kt(ma,{title:"Align",children:[Re(xn,{label:"Grid spacing",children:Re("input",{className:"se-numberInput","aria-label":"Grid spacing",type:"number",min:.001,step:.1,value:e.composition.gridSize,onChange:o=>{let n=Number(o.target.value);Number.isFinite(n)&&n>0&&e.onGridSize(n)}})}),Kt(to,{children:[Re("button",{type:"button",className:"bb-button",onClick:()=>e.onSnap(t.id),children:"Snap to grid"}),Re("button",{type:"button",className:"bb-button",disabled:!t.ready,onClick:()=>e.onGround(t.url),children:"Place on ground"})]})]}),Kt(to,{children:[Kt("button",{type:"button",className:"bb-button",disabled:e.busy||!t.ready,onClick:()=>e.onDuplicate(t.url),children:[Re(Qm,{size:13,"aria-hidden":"true"}),"Duplicate"]}),Kt("button",{type:"button",className:"bb-button",disabled:e.busy||e.assets.length<2,title:a,onClick:()=>e.onDelete(t.url),children:[Re(of,{size:13,"aria-hidden":"true"}),"Delete"]})]}),Re("p",{className:"rui-footnote",title:"Instance ID",children:Re("code",{children:t.id})})]})]})}import{useEffect as rf,useId as af,useRef as _c,useState as sf}from"react";import{ChevronDown as lf,Download as df,FileArchive as cf,FileCode2 as pf,FileJson as Vc,Upload as uf}from"lucide-react";import{jsx as Mt,jsxs as ar}from"react/jsx-runtime";function Kc({action:e,groups:t,busy:i}){let[a,o]=sf(!1),n=_c(null),d=_c(null),s=af(),p=i||t.every(c=>c.options.every(x=>x.disabled));return rf(()=>{if(!a)return;let c=x=>{n.current?.contains(x.target)||o(!1)};return window.addEventListener("pointerdown",c),()=>window.removeEventListener("pointerdown",c)},[a]),ar("div",{className:"bb-exportMenuWrapper",ref:n,onKeyDown:c=>{c.key!=="Escape"||!a||(c.preventDefault(),c.stopPropagation(),o(!1),d.current?.focus())},children:[ar("button",{ref:d,type:"button",className:e==="Export"?"bb-button bb-button--primary":"bb-barButton",disabled:p,"aria-busy":i||void 0,onClick:()=>o(c=>!c),title:`${e} files`,"aria-label":`${e} files`,"aria-expanded":a,"aria-controls":a?s:void 0,children:[e==="Import"?Mt(uf,{size:14,"aria-hidden":"true"}):Mt(df,{size:14,"aria-hidden":"true"}),e,Mt(lf,{size:12})]}),a&&Mt("div",{className:"bb-exportMenu",id:s,role:"group","aria-label":`${e} options`,children:t.map((c,x)=>ar("div",{className:"bb-fileMenuScope",children:[Mt("div",{className:"bb-exportMenuTitle",children:c.title}),Mt("p",{className:"bb-exportMenuDescription",id:`${s}-${x}`,children:c.description}),c.options.map(h=>ar("button",{type:"button",className:"bb-exportMenuItem",disabled:h.disabled||i,"aria-label":`${e} ${h.label}`,"aria-describedby":`${s}-${x}`,onClick:()=>{o(!1),h.run()},children:[h.icon,h.label]},h.label))]},c.title))})]})}function Gc(e,t,i){return[...i?[{title:"Complete scene",description:"Every model, placement, texture, binding, and scene setting. Remote assets keep their URLs.",options:[{label:"Complete scene ZIP",icon:Mt(cf,{size:14}),disabled:e==="Import"?i.importDisabled:i.exportDisabled,run:e==="Import"?i.onImport:i.onExport}]}]:[],...t.map(a=>({title:a.title,description:a.description,options:e==="Import"?[{label:`${a.title} JSON`,icon:Mt(Vc,{size:14}),disabled:a.importDisabled,run:a.onImport}]:[{label:`${a.title} JSON`,icon:Mt(Vc,{size:14}),disabled:a.exportDisabled,run:a.onExportJson},{label:`${a.title} TypeScript`,icon:Mt(pf,{size:14}),disabled:a.exportDisabled,run:a.onExportTs}]}))]}function qc({scopes:e,sceneBundle:t,busy:i}){return Mt(Kc,{action:"Export",groups:Gc("Export",e,t),busy:i})}function Wc({scopes:e,sceneBundle:t,busy:i}){return Mt(Kc,{action:"Import",groups:Gc("Import",e,t),busy:i})}import{Box as bf,ChevronDown as gf,CodeXml as mf,Maximize2 as ff,MousePointer2 as hf,Move3d as xf,Redo2 as vf,Rotate3d as yf,Search as wf,SquareSplitHorizontal as Sf,Undo2 as kf}from"lucide-react";import{jsx as ve,jsxs as Bn}from"react/jsx-runtime";var sr=[{id:"select",label:"Select",shortcut:"V",icon:ve(hf,{size:15})},{id:"move",label:"Move",shortcut:"G",icon:ve(xf,{size:15})},{id:"rotate",label:"Rotate",shortcut:"R",icon:ve(yf,{size:15})},{id:"scale",label:"Scale",shortcut:"T",icon:ve(ff,{size:15})}],Cf=typeof navigator<"u"&&/Mac|iPhone|iPad/.test(navigator.platform)?"\u2318K":"Ctrl K";function Yc({modelName:e,modelMenu:t,canUndo:i,canRedo:a,undoTarget:o,onUndo:n,onRedo:d,tool:s,onToolChange:p,space:c,onSpaceChange:x,hasModel:h,compareOpen:g,onToggleCompare:C,codeOpen:M,onToggleCode:y,onOpenCommands:T,start:f,xrToolsSlot:u,fileActions:v}){return Bn("header",{className:"bb-topBar",children:[ve("span",{className:"bb-topBarLogo",role:"img","aria-label":"Binding Builder",children:ve(bf,{size:14,"aria-hidden":"true"})}),t?ve(Zn,{label:e,title:"Model actions",children:t}):ve("span",{className:"bb-topBarModel",children:e}),f,ve("span",{className:"bb-topBarDivider"}),ve("button",{type:"button",className:"bb-toolButton",disabled:!i,onClick:n,title:`Undo ${o} change (Cmd/Ctrl+Z)`,"aria-label":`Undo ${o} change`,children:ve(kf,{size:15})}),ve("button",{type:"button",className:"bb-toolButton",disabled:!a,onClick:d,title:`Redo ${o} change (Cmd/Ctrl+Shift+Z)`,"aria-label":`Redo ${o} change`,children:ve(vf,{size:15})}),ve("span",{className:"bb-topBarDivider"}),ve("div",{className:"bb-toolGroup",role:"radiogroup","aria-label":"Transform tool",children:sr.map(m=>ve("button",{type:"button",role:"radio","aria-checked":s===m.id,"aria-label":`${m.label} tool`,disabled:!h,className:`bb-toolButton ${s===m.id?"bb-toolButton--active":""}`,onClick:()=>p(m.id),title:`${m.label} (${m.shortcut})`,children:m.icon},m.id))}),Bn("label",{className:"bb-topBarSelect",title:"Transform axes",children:[ve("span",{className:"bb-visuallyHidden",children:"Transform axes"}),Bn("select",{value:c,onChange:m=>x(m.target.value),children:[ve("option",{value:"world",children:"World"}),ve("option",{value:"local",children:"Local"})]}),ve(gf,{size:12,"aria-hidden":"true"})]}),ve("span",{className:"bb-topBarSpacer"}),Bn("button",{type:"button",className:"bb-commandButton",onClick:T,"aria-keyshortcuts":"Meta+K Control+K",children:[ve(wf,{size:13,"aria-hidden":"true"}),ve("span",{children:"Search settings"}),ve("kbd",{children:Cf})]}),ve("span",{className:"bb-topBarSpacer"}),ve("span",{ref:u,className:"bb-topBarXR"}),h?Bn("button",{type:"button",className:`bb-barButton ${g?"bb-barButton--active":""}`,onClick:C,"aria-pressed":g,title:"Drag a divider across the preview to see it before and after your changes",children:[ve(Sf,{size:14,"aria-hidden":"true"}),"Compare"]}):null,Bn("button",{type:"button",className:`bb-barButton ${M?"bb-barButton--active":""}`,onClick:y,"aria-pressed":M,title:"Show the code this editor produces",children:[ve(mf,{size:14,"aria-hidden":"true"}),"Code"]}),v]})}import{useCallback as Jc,useRef as Mf,useState as Xc}from"react";import{Copy as Pf}from"lucide-react";async function lr(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}import{Fragment as Tf,jsx as Co,jsxs as Go}from"react/jsx-runtime";function Zc(){let[e,t]=Xc(null),[i,a]=Xc(null),o=Mf(null),n=Jc(s=>{let c=s.target.closest?.("[data-ri-path]")?.dataset.riPath??null;c!==o.current&&(o.current=c,t(c))},[]),d=Jc(s=>{let p=s.target.closest?.("[data-ri-path]");p?.dataset.riPath&&(s.preventDefault(),a({x:s.clientX,y:s.clientY,path:p.dataset.riPath}))},[]);return{path:e,menu:i,closeMenu:()=>a(null),onMouseOver:n,onContextMenu:d}}function Qc({x:e,y:t,path:i,onClose:a}){return Co("div",{className:"bb-pathMenuScrim",onPointerDown:a,onContextMenu:o=>{o.preventDefault(),a()},children:Go("div",{className:"bb-pathMenu",style:{left:e,top:t},role:"menu",onPointerDown:o=>o.stopPropagation(),children:[Go("button",{type:"button",role:"menuitem",autoFocus:!0,onKeyDown:o=>{o.key==="Escape"&&a()},onClick:()=>{lr(i),a()},children:[Co(Pf,{size:13,"aria-hidden":"true"}),"Copy path"]}),Co("code",{children:i})]})})}function Bf({path:e}){let t=e.lastIndexOf(".");return Go(Tf,{children:[e.slice(0,t+1),Co("em",{children:e.slice(t+1)})]})}function ep({saveState:e,objectCount:t,selectedCount:i,path:a,hints:o}){return Go("footer",{className:"bb-statusBar",children:[e?Go("span",{className:"bb-statusSave",children:[Co("i",{"aria-hidden":"true"}),e]}):null,Go("span",{children:[t," ",t===1?"object":"objects"]}),i>0?Go("span",{children:[i," selected"]}):null,Co("span",{className:"bb-statusPath","aria-live":"off",children:a?Co(Bf,{path:a}):null}),Co("span",{className:"bb-statusHints",children:o})]})}import{jsx as Rf}from"react/jsx-runtime";function ii({orientation:e,label:t,onPointerDown:i,onKeyDown:a}){return Rf("div",{className:`bb-resizer bb-resizer--${e}`,role:"separator","aria-orientation":e,"aria-label":t,tabIndex:0,onPointerDown:i,onKeyDown:a})}import{useCallback as Oa,useEffect as Nf,useRef as Af,useState as Of}from"react";var op="react-immersive:editor-panels";function tp(){try{return JSON.parse(localStorage.getItem(op)??"{}")}catch{return{}}}function dr(e,{size:t,min:i,max:a,edge:o,open:n=!0}){let[d,s]=Of(()=>{let g=tp()[e];return{size:g&&Number.isFinite(g.size)?Math.min(a,Math.max(i,g.size)):t,open:g?.open??n}}),p=Af(d);p.current=d,Nf(()=>{try{localStorage.setItem(op,JSON.stringify({...tp(),[e]:d}))}catch{}},[e,d]);let c=Oa(g=>s(C=>({...C,open:g})),[]),x=Oa(g=>{if(g.button!==0)return;g.preventDefault();let C=g.currentTarget;C.setPointerCapture(g.pointerId);let M=o==="top"?g.clientY:g.clientX,y=p.current.size,T=o==="right"?1:-1,f=v=>{let m=o==="top"?v.clientY:v.clientX,N=Math.min(a,Math.max(i,y+(m-M)*T));s(A=>({...A,size:N}))},u=()=>{C.removeEventListener("pointermove",f),C.removeEventListener("pointerup",u),C.removeEventListener("pointercancel",u)};C.addEventListener("pointermove",f),C.addEventListener("pointerup",u),C.addEventListener("pointercancel",u)},[o,i,a]),h=Oa(g=>{let C=o==="top"?"ArrowUp":o==="right"?"ArrowRight":"ArrowLeft",M=o==="top"?"ArrowDown":o==="right"?"ArrowLeft":"ArrowRight";if(g.key!==C&&g.key!==M)return;g.preventDefault(),g.stopPropagation();let y=(g.key===C?1:-1)*16;s(T=>({...T,size:Math.min(a,Math.max(i,T.size+y))}))},[o,i,a]);return{size:d.size,open:d.open,setOpen:c,startResize:x,onResizeKey:h}}import{useEffect as Ef}from"react";import{X as jf}from"lucide-react";import{jsx as Ea,jsxs as If}from"react/jsx-runtime";function np({toast:e,onDismiss:t}){return Ef(()=>{if(!e||e.tone!=="success")return;let i=window.setTimeout(t,3e3);return()=>window.clearTimeout(i)},[e,t]),e?If("div",{className:`bb-toast bb-toast--${e.tone}`,role:e.tone==="error"?"alert":"status",children:[Ea("span",{children:e.text}),Ea("button",{type:"button","aria-label":"Dismiss message",onClick:t,children:Ea(jf,{size:13})})]}):null}import{memo as zf,useMemo as Lf,useState as rp}from"react";import{Check as Df,Copy as Ff,X as Hf}from"lucide-react";function ri(e){return JSON.stringify(e,null,2)}function cr(e){return['import { defineObjectBindings } from "@liveroom-tech/react-immersive/utils";',"",`export const objectBindings = defineObjectBindings(${JSON.stringify(e,null,2)});`,""].join(`
|
|
2
2
|
`)}function pr(e){return JSON.stringify(e,null,2)}function ur(e){return['import type { SceneConfig } from "@liveroom-tech/react-immersive/utils";',"",`export const sceneConfig: SceneConfig = ${JSON.stringify(e,null,2)};`,""].join(`
|
|
3
|
-
`)}function ip(e,t,i){fn(new Blob([t],{type:i}),e)}function ja(e){return JSON.stringify(e??{},null,2)}function Ia(e){return`[${e[0].toFixed(3)}, ${e[1].toFixed(3)}, ${e[2].toFixed(3)}]`}import{jsx as zt,jsxs as ap}from"react/jsx-runtime";var $f={model:["model","wireframe"],camera:["camera"],world:["environment","background","groundShadows"],lighting:["lighting","shadows"],postProcessing:["postProcessing"],rules:["styleRules"],product:["product"]};function Uf(e){return!e||typeof e!="object"?e:Object.fromEntries(Object.entries(e).filter(([,t])=>t?.enabled))}var sp=zf(function({scope:t,selectedKey:i,selectedBinding:a,sceneConfig:o,sceneTab:n,onClose:d}){let[s,p]=rp("ts"),[c,x]=rp(!1),{preview:h,full:g,caption:C}=Lf(()=>{if(t==="object"){if(!i||!a)return{preview:"",full:"",caption:"Select an object to see its binding."};let T={[i]:a};return{preview:ri(T),full:s==="ts"?cr(T):ri(T),caption:"objectBindings"}}let M=$f[n]??[],y=Object.fromEntries(M.map(T=>[T,T==="postProcessing"?Uf(o[T]):o[T]]));return{preview:JSON.stringify(y,null,2),full:s==="ts"?ur(o):pr(o),caption:"sceneConfig"}},[t,i,a,o,n,s]);return ap("section",{className:"bb-codePanel","aria-label":"Code",children:[ap("header",{children:[zt("strong",{children:"Code"}),zt("code",{children:C}),zt("span",{className:"bb-topBarSpacer"}),zt("div",{className:"bb-codeFormat",role:"radiogroup","aria-label":"Code format",children:["ts","json"].map(M=>zt("button",{type:"button",role:"radio","aria-checked":s===M,className:s===M?"is-active":"",onClick:()=>p(M),children:M==="ts"?"TS":"JSON"},M))}),zt("button",{type:"button",className:"bb-toolButton bb-toolButton--small",disabled:!g,title:t==="scene"?"Copy the whole scene config":"Copy this binding","aria-label":t==="scene"?"Copy the whole scene config":"Copy this binding",onClick:async()=>{await lr(g),x(!0),window.setTimeout(()=>x(!1),1500)},children:c?zt(Df,{size:13}):zt(Ff,{size:13})}),zt("button",{type:"button",className:"bb-toolButton bb-toolButton--small","aria-label":"Close code panel",onClick:d,children:zt(Hf,{size:13})})]}),zt("pre",{tabIndex:0,children:h})]})});import{useEffect as za,useMemo as _f,useRef as dp,useState as lp}from"react";import{Search as Vf}from"lucide-react";import{jsx as Lt,jsxs as qo}from"react/jsx-runtime";function Kf(e,t){let i=e.label.toLowerCase(),a=`${i} ${e.hint} ${e.keywords??""}`.toLowerCase(),o=0;for(let n of t){if(!a.includes(n))return-1;o+=i.startsWith(n)?3:i.includes(n)?2:1}return o}function cp({commands:e,onClose:t}){let[i,a]=lp(""),[o,n]=lp(0),d=dp(null),s=_f(()=>{let c=i.toLowerCase().split(/\s+/).filter(Boolean);return c.length?e.map(x=>({command:x,value:Kf(x,c)})).filter(x=>x.value>=0).sort((x,h)=>h.value-x.value).slice(0,40).map(x=>x.command):e.slice(0,40)},[e,i]);za(()=>n(0),[i]),za(()=>{d.current?.children[o]?.scrollIntoView({block:"nearest"})},[o]);let p=c=>{c&&(t(),c.run())};return Lt("div",{className:"bb-paletteBackdrop",onMouseDown:c=>{c.target===c.currentTarget&&t()},children:qo("div",{className:"bb-palette",role:"dialog","aria-modal":"true","aria-label":"Search settings",children:[qo("label",{className:"bb-paletteSearch",children:[Lt(Vf,{size:14,"aria-hidden":"true"}),Lt("input",{autoFocus:!0,role:"combobox","aria-expanded":"true","aria-controls":"bb-paletteList","aria-activedescendant":s[o]?`bb-palette-${s[o].id}`:void 0,"aria-label":"Search settings and commands",placeholder:"Search settings and commands",value:i,onChange:c=>a(c.target.value),onKeyDown:c=>{c.key==="ArrowDown"&&(c.preventDefault(),n(x=>Math.min(s.length-1,x+1))),c.key==="ArrowUp"&&(c.preventDefault(),n(x=>Math.max(0,x-1))),c.key==="Enter"&&(c.preventDefault(),p(s[o])),c.key==="Escape"&&(c.preventDefault(),c.stopPropagation(),t())}})]}),qo("div",{className:"bb-paletteList",id:"bb-paletteList",role:"listbox",ref:d,children:[s.map((c,x)=>qo("button",{id:`bb-palette-${c.id}`,type:"button",role:"option","aria-selected":x===o,tabIndex:-1,className:x===o?"is-active":"",onMouseMove:()=>n(x),onClick:()=>p(c),children:[Lt("span",{children:c.label}),c.shortcut?Lt("kbd",{children:c.shortcut}):null,Lt("small",{children:c.hint})]},c.id)),s.length?null:qo("p",{children:["Nothing matches \u201C",i,"\u201D."]})]})]})})}function pp({onClose:e}){let t=dp(null);return za(()=>t.current?.focus(),[]),Lt("div",{className:"bb-paletteBackdrop",onMouseDown:a=>{a.target===a.currentTarget&&e()},children:Lt("div",{ref:t,tabIndex:-1,className:"bb-shortcuts",role:"dialog","aria-modal":"true","aria-label":"Keyboard shortcuts",onKeyDown:a=>{(a.key==="Escape"||a.key==="?")&&(a.preventDefault(),a.stopPropagation(),e())},children:[["Tools",[["V","Select"],["G","Move"],["R","Rotate"],["T","Scale"],["F","Frame selection"]]],["Editor",[["\u2318K","Search settings"],["\u2318Z","Undo"],["\u21E7\u2318Z","Redo"],["?","Shortcuts"],["Esc","Clear selection"]]],["Camera",[["W A S D","Move"],["Space / C","Up and down"],["Arrows","Orbit"],["\u21E7 Up / Down","Zoom"]]],["Selecting",[["Click","Select"],["\u2318 Click","Add or remove"],["\u21E7 Click","Add in the viewport, range in the Outliner"],["\u2318A","All shown in the Outliner"]]]].map(([a,o])=>qo("section",{children:[Lt("h4",{children:a}),o.map(([n,d])=>qo("div",{children:[Lt("span",{children:d}),Lt("kbd",{children:n})]},d))]},a))})})}var je=(e,t)=>({panel:"object",tab:e,section:t}),ue=(e,t)=>({panel:"scene",tab:e,section:t}),up=[{label:"Object ID",hint:"Object \u203A General",keywords:"identity id modelObjectId",where:je("general","Identity")},{label:"Label, type, status, group, tags",hint:"Object \u203A General",keywords:"basics selectable hoverable visible",where:je("general","Basics")},{label:"Position, rotation, scale",hint:"Object \u203A General",keywords:"transform move pivot",where:je("general","Transform")},{label:"Saved view",hint:"Object \u203A General",keywords:"camera position cameraState",where:je("general","Saved view")},{label:"Material presets",hint:"Object \u203A Material",keywords:"wood metal glass plastic",where:je("material")},{label:"Base color",hint:"Object \u203A Material",keywords:"pbr albedo texture metalness baseColor",where:je("material","Surface")},{label:"Roughness",hint:"Object \u203A Material",keywords:"glossiness matte shiny",where:je("material","Roughness")},{label:"Opacity",hint:"Object \u203A Material",keywords:"alpha transparency blending",where:je("material","Opacity")},{label:"Emission",hint:"Object \u203A Material",keywords:"emissive glow",where:je("material","Emission")},{label:"Normal and bump maps",hint:"Object \u203A Material",keywords:"normalMap bumpMap",where:je("material","Normal and bump")},{label:"Displacement",hint:"Object \u203A Material",keywords:"height map",where:je("material","Displacement")},{label:"Ambient occlusion map",hint:"Object \u203A Material",keywords:"aoMap",where:je("material","Ambient occlusion")},{label:"Clearcoat",hint:"Object \u203A Material",keywords:"lacquer gloss layer",where:je("material","Clearcoat")},{label:"Sheen",hint:"Object \u203A Material",keywords:"fabric velvet",where:je("material","Sheen")},{label:"Anisotropy",hint:"Object \u203A Material",keywords:"brushed metal",where:je("material","Anisotropy")},{label:"Transmission and volume",hint:"Object \u203A Material",keywords:"glass thickness attenuation",where:je("material","Transmission and volume")},{label:"Faces",hint:"Object \u203A Material",keywords:"side double backface",where:je("material","Faces")},{label:"Decals",hint:"Object \u203A Decals",keywords:"logo text image print",where:je("decals")},{label:"Actions",hint:"Object \u203A Actions",keywords:"onAction button command",where:je("actions")},{label:"Metrics",hint:"Object \u203A Data",keywords:"json",where:je("data","Metrics")},{label:"Metadata",hint:"Object \u203A Data",keywords:"json",where:je("data","Metadata")},{label:"Model rotation",hint:"Scene \u203A Model",keywords:"straighten orient",where:ue("model","Display")},{label:"Renderer and shading",hint:"Scene \u203A Model",keywords:"pbr matcap uv checker lit unlit normals",where:ue("model","Display")},{label:"Material variants",hint:"Scene \u203A Model",keywords:"KHR_materials_variants",where:ue("model","Display")},{label:"Auto rotate",hint:"Scene \u203A Model",keywords:"turntable spin",where:ue("model","Auto rotate")},{label:"Wireframe",hint:"Scene \u203A Model",where:ue("model","Wireframe")},{label:"Diagnostics",hint:"Scene \u203A Model",keywords:"asset statistics triangles textures",where:ue("model","Diagnostics")},{label:"Field of view",hint:"Scene \u203A Camera",keywords:"fov lens",where:ue("camera","Lens")},{label:"Environment",hint:"Scene \u203A World",keywords:"hdri preset intensity rotation ibl",where:ue("world","Environment")},{label:"Environment shadow",hint:"Scene \u203A World",keywords:"shadowLight",where:ue("world","Environment shadow")},{label:"Background",hint:"Scene \u203A World",keywords:"color image environment",where:ue("world","Background")},{label:"Ground shadows",hint:"Scene \u203A World",keywords:"contact catcher",where:ue("world","Ground shadows")},{label:"Lights",hint:"Scene \u203A Lights",keywords:"directional point spot hemisphere",where:ue("lighting","Lights")},{label:"Shadows",hint:"Scene \u203A Lights",keywords:"map size bias softness",where:ue("lighting","Shadows")},{label:"Effects",hint:"Scene \u203A Effects",keywords:"post processing bloom ssao tone mapping vignette depth of field",where:ue("postProcessing")},{label:"Tone mapping",hint:"Scene \u203A Effects",keywords:"post processing effect aces filmic exposure",where:ue("postProcessing","Tone mapping")},{label:"Brightness and contrast",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Brightness and contrast")},{label:"Hue and saturation",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Hue and saturation")},{label:"Vignette",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Vignette")},{label:"Bloom",hint:"Scene \u203A Effects",keywords:"post processing effect glow threshold",where:ue("postProcessing","Bloom")},{label:"Ambient occlusion (SSAO)",hint:"Scene \u203A Effects",keywords:"post processing effect ssao",where:ue("postProcessing","Ambient occlusion")},{label:"Depth of field",hint:"Scene \u203A Effects",keywords:"post processing effect bokeh blur focus",where:ue("postProcessing","Depth of field")},{label:"God rays",hint:"Scene \u203A Effects",keywords:"post processing effect sun",where:ue("postProcessing","God rays")},{label:"Lens flare",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Lens flare")},{label:"Outline",hint:"Scene \u203A Effects",keywords:"post processing effect edge",where:ue("postProcessing","Outline")},{label:"Anti-aliasing (SMAA)",hint:"Scene \u203A Effects",keywords:"post processing effect smaa",where:ue("postProcessing","Anti-aliasing")},{label:"Chromatic aberration",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Chromatic aberration")},{label:"Glitch",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Glitch")},{label:"Noise",hint:"Scene \u203A Effects",keywords:"post processing effect grain",where:ue("postProcessing","Noise")},{label:"Pixelation",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Pixelation")},{label:"Section cut",hint:"Scene \u203A Model",keywords:"clip plane box slice",where:ue("model","Section cut")},{label:"Configure: customer choices",hint:"Configure",keywords:"product configurator options swatch variant customise customize choices shop e-commerce",where:{panel:"configure",tab:"configure"}},{label:"Configure: prices and buying",hint:"Configure",keywords:"price sku checkout buy link cart currency commerce",where:{panel:"configure",tab:"configure",section:"Prices and buying"}},{label:"Configure: restrictions",hint:"Configure",keywords:"compatibility rules requires excludes combinations",where:{panel:"configure",tab:"configure",section:"Restrictions"}},{label:"Configure: publish and embed",hint:"Configure",keywords:"embed publish share website shopify wordpress",where:{panel:"configure",tab:"configure",section:"Publish"}},{label:"Rules",hint:"Scene \u203A Rules",keywords:"style rules styleRules metric status color scale pulse",where:ue("rules")},{label:"Assets",hint:"Left panel",keywords:"models placements grid composition",where:{panel:"left",tab:"assets"}},{label:"Annotations",hint:"Left panel",keywords:"hotspots markers notes",where:{panel:"left",tab:"annotations"}},{label:"Measurements",hint:"Left panel",keywords:"distance area calibrate units",where:{panel:"left",tab:"measure"}},{label:"Sequences",hint:"Timeline",keywords:"keyframes tracks timeline",where:{panel:"dock",tab:"sequences"}},{label:"Clips",hint:"Timeline",keywords:"animations autoplay loop speed",where:{panel:"dock",tab:"clips"}},{label:"Cinematic",hint:"Timeline",keywords:"waypoints camera path",where:{panel:"dock",tab:"cinematic"}}];function bp(e){requestAnimationFrame(()=>{let t=document.querySelector(`.bb-root [data-ri-section="${CSS.escape(e)}"]`);if(!t)return;let i=t.querySelector('button[aria-expanded="false"]');i?.closest("[data-ri-section]")===t&&i.click(),t.scrollIntoView({block:"nearest"}),t.classList.add("bb-flash"),window.setTimeout(()=>t.classList.remove("bb-flash"),900)})}import{useEffect as Zf,useRef as Qf,useState as br}from"react";import{Lock as eh,Plus as th,Trash2 as oh}from"lucide-react";import{RotateCcw as Gf}from"lucide-react";import{jsx as ai}from"react/jsx-runtime";function ut({panelKey:e,title:t,tooltip:i,toggleLabel:a,controls:o,children:n,requiredTier:d,core:s=!1}){let{openMaterialPanels:p,materialPanelEnabled:c,onToggleMaterialPanel:x,onSetMaterialPanelState:h}=o,g=d?.locked??!1;return o.visibleLayers.has(e)?ai(Uc,{title:t,tooltip:i,disabled:g||!s&&!c[e],open:p[e],onToggle:()=>x(e),trailing:s?ai("button",{type:"button",className:"se-iconButton",title:`Clear ${t.toLowerCase()} overrides`,"aria-label":`Clear ${t.toLowerCase()} overrides`,onClick:()=>h(e,!1),children:ai(Gf,{size:12})}):ai(se,{checked:!g&&c[e],onChange:g?()=>{}:C=>h(e,C),label:a??`Toggle ${t}`}),children:g&&d?ai(We,{requiredTier:d.tier,feature:t}):n}):null}import{createContext as qf,useContext as Wf,useRef as Yf}from"react";import{FileUp as Jf}from"lucide-react";import{jsx as Ie,jsxs as Mo}from"react/jsx-runtime";var La=qf(null);function Fe({label:e,value:t,placeholder:i,onChange:a,path:o}){let n=Yf(null),d=Wf(La);return Mo("div",{className:"bb-field bb-field--row","data-ri-path":o,children:[Ie("label",{className:"bb-label",title:e,children:e}),Mo("div",{className:"bb-fileField",title:d??void 0,children:[Ie("input",{className:"bb-input bb-fileField-input",placeholder:i,value:t,disabled:!!d&&!t,onChange:s=>{let p=s.target.value;!p&&t&&qn(t),a(p)}}),Ie("button",{type:"button",className:"bb-fileFieldButton",disabled:!!d,onClick:()=>n.current?.click(),"aria-label":`Select file for ${e}`,title:`Select file for ${e}`,children:Ie(Jf,{size:13})}),Ie("input",{ref:n,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif",className:"bb-hiddenInput",onChange:s=>{let p=s.target.files?.[0];if(!p)return;let c=gn(p);t&&t!==c&&qn(t),It(c,URL.createObjectURL(p)),a(c),s.target.value=""}})]})]})}function Po({label:e,value:t,fallback:i="#ffffff",onChange:a,path:o}){return Mo("div",{className:"bb-field bb-field--row","data-ri-path":o,children:[Ie("span",{className:"bb-label",children:e}),Ie(Rd,{label:e,value:t||i,onChange:a})]})}function si({label:e,checked:t,onChange:i,path:a}){return Mo("label",{className:"bb-field bb-field--row","data-ri-path":a,children:[Ie("span",{className:"bb-label",title:e,children:e}),Ie("span",{className:"rui-checkCell",children:Ie("input",{type:"checkbox",checked:t,onChange:o=>i(o.target.checked)})})]})}function gp({label:e,value:t,min:i,max:a,step:o,placeholder:n,disabled:d,onChange:s,path:p}){return Mo("div",{className:"bb-field bb-field--row","data-ri-path":p,children:[Ie("label",{className:"bb-label",title:e,children:e}),Ie("input",{className:"bb-input",type:"number",min:i,max:a,step:o,placeholder:n,disabled:d,value:t??"",onChange:c=>s(c.target.value===""?void 0:Number(c.target.value))})]})}function Xf(e,t){let i=t<1?Math.ceil(-Math.log10(t)):0,a=10**Math.max(i,0);return Math.round(e*a)/a}function Da({label:e,value:t,min:i,max:a,step:o=.01,disabled:n,onChange:d,path:s}){let p=t??0,c=h=>{let g=h;return i!==void 0&&(g=Math.max(i,g)),a!==void 0&&(g=Math.min(a,g)),g},x=Bd({value:p,step:o,min:i,max:a,disabled:n,onChange:h=>d(Xf(h,o))});return Mo("div",{className:"bb-field bb-field--row","data-ri-path":s,children:[Ie("label",{className:"bb-label bb-label--scrub",title:"Drag to change",...x,children:e}),Ie("input",{className:"bb-input",type:"number",min:i,max:a,step:o,disabled:n,value:p,onChange:h=>{h.target.value!==""&&d(c(Number(h.target.value)))}})]})}function Tn({label:e,value:t,options:i,onChange:a,path:o}){return Mo("div",{className:"bb-field bb-field--row","data-ri-path":o,children:[Ie("label",{className:"bb-label",title:e,children:e}),i.length<=3?Ie("div",{className:"se-segmentedControl",children:i.map(n=>Ie("button",{type:"button",className:`se-segmentedOption ${n===t?"se-segmentedOption--active":""}`,onClick:()=>a(n),children:n.charAt(0).toUpperCase()+n.slice(1)},n))}):Ie("select",{className:"bb-select",value:t,onChange:n=>a(n.target.value),children:i.map(n=>Ie("option",{value:n,children:n.charAt(0).toUpperCase()+n.slice(1)},n))})]})}function ye({label:e,value:t,min:i,max:a,step:o,onChange:n,path:d}){return Mo("div",{className:"bb-field bb-field--row","data-ri-path":d,children:[Ie("span",{className:"bb-label",children:e}),Ie(Td,{label:e,value:t??i,unset:t===void 0,min:i,max:a,step:o,onChange:n})]})}import{Fragment as hp,jsx as z,jsxs as Ae}from"react/jsx-runtime";var mp="This object has no texture coordinates (UVs), so image maps can't be placed on it. Colors and the other settings work, and Decals can put an image on it.",fp=[{key:"pbr",label:"Surface",core:!0},{key:"roughness",label:"Roughness",core:!0},{key:"opacity",label:"Opacity",core:!0},{key:"normalBump",label:"Normal and bump"},{key:"emission",label:"Emission"},{key:"ao",label:"Ambient occlusion"},{key:"faces",label:"Faces"},{key:"displacement",label:"Displacement",advanced:!0},{key:"clearcoat",label:"Clearcoat",advanced:!0},{key:"sheen",label:"Sheen",advanced:!0},{key:"anisotropy",label:"Anisotropy",advanced:!0},{key:"transmission",label:"Transmission and volume",advanced:!0}];function xp({selectedItem:e,selectedMaterial:t,pbrWorkflow:i,onPbrWorkflowChange:a,openMaterialPanels:o,materialPanelEnabled:n,onToggleMaterialPanel:d,onSetMaterialPanelState:s,updateSelectedMaterial:p,setSelectedTexturePath:c,isTexturePositioningEnabled:x,onConfirmTexturePosition:h,takesImage:g=!0}){let{tier:C}=it(),M={tier:"starter",locked:!nt(C,"advancedMaterials")},[y,T]=br(()=>new Set),[f,u]=br(!1),v=Qf(null);hn([v],()=>u(!1),f),Zf(()=>T(new Set),[e]);let m=new Set(fp.filter(w=>w.core||n[w.key]||y.has(w.key)).map(w=>w.key)),N=fp.filter(w=>!m.has(w.key)),A=w=>{u(!1),T(I=>new Set(I).add(w)),s(w,!0),o[w]||d(w)},G={openMaterialPanels:o,materialPanelEnabled:n,onToggleMaterialPanel:d,onSetMaterialPanelState:s,visibleLayers:m},[B,P]=br("roughness"),[$,H]=br("factor"),de=(w,I)=>{p(e,he=>{if(!he?.texture?.path)return he??{};let Ne=he.texture.offset??[0,0],j=[Ne[0],Ne[1]];return j[w]=I,{...he,texture:{...he.texture,offset:j}}})},_=w=>{p(e,I=>{if(!I?.texture?.path)return I??{};let he=(w%360+360)%360;return{...I,texture:{...I.texture,rotation:he*Math.PI/180}}})},Q=()=>{c(e,"texture","")};return Ae(La.Provider,{value:g?null:mp,children:[g?null:z("p",{className:"bb-note bb-materialNotice",children:mp}),z(ut,{panelKey:"pbr",core:!0,title:"Surface",tooltip:"Controls the base color and workflow used for physically based shading.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Tn,{label:"Workflow",value:i,options:["metalness","specular"],onChange:a}),z(Fe,{path:"objectBindings[\u2026].style.material.texture.path",label:i==="specular"?"Albedo map":"Base map",placeholder:"materials/oak-wood.jpg",value:t?.texture?.path??"",onChange:w=>c(e,"texture",w)}),t?.texture?.path?Ae("div",{className:"rui-group",children:[Ae("div",{className:"rui-groupHeader",children:[z("span",{children:"Texture position"}),z("button",{type:"button",className:"se-iconButton",onClick:Q,title:"Remove the texture and its position","aria-label":"Remove the texture and its position",children:z(oh,{size:13})})]}),Ae("div",{className:"bb-grid",children:[z(Da,{path:"objectBindings[\u2026].style.material.texture.offset",label:"Offset X",value:t?.texture?.offset?.[0]??0,step:.01,onChange:w=>de(0,w)}),z(Da,{path:"objectBindings[\u2026].style.material.texture.offset",label:"Offset Y",value:t?.texture?.offset?.[1]??0,step:.01,onChange:w=>de(1,w)})]}),z(ye,{label:"Rotation",value:((t?.texture?.rotation??0)*180/Math.PI%360+360)%360,min:0,max:360,step:1,onChange:w=>_(w??0)}),x?z("button",{type:"button",className:"bb-button rui-inlineButton",onClick:h,title:"Confirm this texture position and exit positioning mode",children:"Done positioning"}):z("p",{className:"bb-note",style:{margin:"6px 0 0"},children:"Double-click the object in the preview to drag its texture directly (scroll to zoom), or edit its offset numerically once positioning."})]}):null,z(Po,{path:"objectBindings[\u2026].style.material.baseColor",label:i==="specular"?"Albedo color":"Base color",value:t?.baseColor??"#ffffff",onChange:w=>p(e,I=>({...I,baseColor:w}))}),i==="metalness"?Ae(hp,{children:[z(ye,{path:"objectBindings[\u2026].style.material.metalness",label:"Metalness",value:t?.metalness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,metalness:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.metalnessMap.path",label:"Metalness map",placeholder:"materials/body-metalness.jpg",value:t?.metalnessMap?.path??"",onChange:w=>c(e,"metalnessMap",w)})]}):Ae(hp,{children:[z(ye,{path:"objectBindings[\u2026].style.material.specularIntensity",label:"Specular intensity",value:t?.specularIntensity,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,specularIntensity:w}))}),z(Po,{path:"objectBindings[\u2026].style.material.specularColor",label:"Specular color",value:t?.specularColor??"#ffffff",onChange:w=>p(e,I=>({...I,specularColor:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.specularIntensityMap.path",label:"Intensity map",placeholder:"materials/body-specular-intensity.jpg",value:t?.specularIntensityMap?.path??"",onChange:w=>c(e,"specularIntensityMap",w)}),z(Fe,{path:"objectBindings[\u2026].style.material.specularColorMap.path",label:"Color map",placeholder:"materials/body-specular-color.jpg",value:t?.specularColorMap?.path??"",onChange:w=>c(e,"specularColorMap",w)})]}),z(ye,{path:"objectBindings[\u2026].style.material.reflectivity",label:"Reflectivity",value:t?.reflectivity,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,reflectivity:w}))})]})}),z(ut,{panelKey:"roughness",core:!0,title:"Roughness",tooltip:"Adjusts how matte or shiny the surface appears.",toggleLabel:"Toggle Roughness and Glossiness",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Tn,{label:"Mode",value:B,options:["roughness","glossiness"],onChange:P}),z("div",{className:"bb-field bb-field--full",children:z("p",{className:"bb-note",children:B==="roughness"?"Roughness: 0 is glossy, 1 is matte.":"Glossiness is the inverse of roughness (glossiness = 1 \u2212 roughness)"})}),B==="roughness"?z(ye,{path:"objectBindings[\u2026].style.material.roughness",label:"Roughness",value:t?.roughness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,roughness:w}))}):z(ye,{path:"objectBindings[\u2026].style.material.roughness",label:"Glossiness",value:t?.roughness===void 0?void 0:1-t.roughness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,roughness:w===void 0?void 0:1-w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.roughnessMap.path",label:B==="glossiness"?"Glossiness map":"Roughness map",placeholder:"materials/body-roughness.jpg",value:t?.roughnessMap?.path??"",onChange:w=>c(e,"roughnessMap",w)})]})}),z(ut,{panelKey:"emission",title:"Emission",tooltip:"Makes the material self-illuminated with emissive color and intensity.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Po,{path:"objectBindings[\u2026].style.material.emissive",label:"Color",value:t?.emissive??"#000000",fallback:"#000000",onChange:w=>p(e,I=>({...I,emissive:w}))}),z(ye,{path:"objectBindings[\u2026].style.material.emissiveIntensity",label:"Intensity",value:t?.emissiveIntensity,min:0,max:10,step:.1,onChange:w=>p(e,I=>({...I,emissiveIntensity:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.emissiveMap.path",label:"Map",placeholder:"materials/body-emissive.jpg",value:t?.emissiveMap?.path??"",onChange:w=>c(e,"emissiveMap",w)})]})}),z(ut,{panelKey:"opacity",core:!0,title:"Opacity",tooltip:"Controls transparency, alpha testing, and blending behavior.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(ye,{path:"objectBindings[\u2026].style.material.opacity",label:"Opacity",value:t?.opacity,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,opacity:w}))}),z(ye,{path:"objectBindings[\u2026].style.material.alphaTest",label:"Alpha test",value:t?.alphaTest,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,alphaTest:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.alphaMap.path",label:"Alpha map",placeholder:"materials/body-alpha.png",value:t?.alphaMap?.path??"",onChange:w=>c(e,"alphaMap",w)}),z(Tn,{path:"objectBindings[\u2026].style.material.blendingMode",label:"Blending mode",value:t?.blendingMode??"normal",options:wd,onChange:w=>p(e,I=>({...I,blendingMode:w}))}),z(si,{path:"objectBindings[\u2026].style.material.alphaHash",label:"Alpha hash",checked:t?.alphaHash??!1,onChange:w=>p(e,I=>({...I,alphaHash:w}))}),z(si,{path:"objectBindings[\u2026].style.material.dithering",label:"Dithering",checked:t?.dithering??!1,onChange:w=>p(e,I=>({...I,dithering:w}))})]})}),Ae(ut,{panelKey:"normalBump",title:"Normal and bump",tooltip:"Adds surface detail without changing the actual mesh shape.",toggleLabel:"Toggle Normal and Bump",controls:G,children:[Ae("div",{className:"bb-grid",children:[z(Fe,{path:"objectBindings[\u2026].style.material.normalMap.path",label:"Normal map",placeholder:"materials/body-normal.jpg",value:t?.normalMap?.path??"",onChange:w=>c(e,"normalMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.normalScale",label:"Normal scale",value:t?.normalScale,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,normalScale:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.bumpMap.path",label:"Bump map",placeholder:"materials/body-bump.jpg",value:t?.bumpMap?.path??"",onChange:w=>c(e,"bumpMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.bumpScale",label:"Bump scale",value:t?.bumpScale,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,bumpScale:w}))})]}),z(si,{path:"objectBindings[\u2026].style.material.flipNormalY",label:"Flip normal Y",checked:t?.flipNormalY??!1,onChange:w=>p(e,I=>({...I,flipNormalY:w}))})]}),z(ut,{panelKey:"displacement",requiredTier:M,title:"Displacement",tooltip:"Offsets geometry using a texture to create real surface height.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Fe,{path:"objectBindings[\u2026].style.material.displacementMap.path",label:"Map",placeholder:"materials/body-displacement.jpg",value:t?.displacementMap?.path??"",onChange:w=>c(e,"displacementMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.displacementScale",label:"Scale",value:t?.displacementScale,min:-5,max:5,step:.01,onChange:w=>p(e,I=>({...I,displacementScale:w}))}),z(ye,{path:"objectBindings[\u2026].style.material.displacementBias",label:"Bias",value:t?.displacementBias,min:-5,max:5,step:.01,onChange:w=>p(e,I=>({...I,displacementBias:w}))})]})}),z(ut,{panelKey:"ao",title:"Ambient occlusion",tooltip:"Darkens creases and contact areas to add depth.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Fe,{path:"objectBindings[\u2026].style.material.aoMap.path",label:"Map",placeholder:"materials/body-ao.jpg",value:t?.aoMap?.path??"",onChange:w=>c(e,"aoMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.aoMapIntensity",label:"Intensity",value:t?.aoMapIntensity,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,aoMapIntensity:w}))})]})}),Ae(ut,{panelKey:"clearcoat",requiredTier:M,title:"Clearcoat",tooltip:"Adds a glossy protective layer on top of the base material.",controls:G,children:[Ae("div",{className:"bb-grid",children:[z(Fe,{path:"objectBindings[\u2026].style.material.clearcoatMap.path",label:"Coat map",placeholder:"materials/body-clearcoat.jpg",value:t?.clearcoatMap?.path??"",onChange:w=>c(e,"clearcoatMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.clearcoat",label:"Clearcoat",value:t?.clearcoat,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,clearcoat:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.clearcoatRoughnessMap.path",label:"Roughness map",placeholder:"materials/body-clearcoat-roughness.jpg",value:t?.clearcoatRoughnessMap?.path??"",onChange:w=>c(e,"clearcoatRoughnessMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.clearcoatRoughness",label:"Roughness",value:t?.clearcoatRoughness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,clearcoatRoughness:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.clearcoatNormalMap.path",label:"Normal map",placeholder:"materials/body-clearcoat-normal.jpg",value:t?.clearcoatNormalMap?.path??"",onChange:w=>c(e,"clearcoatNormalMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.clearcoatNormalScale",label:"Normal scale",value:t?.clearcoatNormalScale,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,clearcoatNormalScale:w}))})]}),z(si,{path:"objectBindings[\u2026].style.material.flipClearcoatNormalY",label:"Flip normal Y",checked:t?.flipClearcoatNormalY??!1,onChange:w=>p(e,I=>({...I,flipClearcoatNormalY:w}))})]}),z(ut,{panelKey:"sheen",requiredTier:M,title:"Sheen",tooltip:"Adds a soft fabric-like sheen on grazing angles.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(ye,{path:"objectBindings[\u2026].style.material.sheen",label:"Sheen",value:t?.sheen,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,sheen:w}))}),z(Po,{path:"objectBindings[\u2026].style.material.sheenColor",label:"Color",value:t?.sheenColor??"#ffffff",onChange:w=>p(e,I=>({...I,sheenColor:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.sheenColorMap.path",label:"Color map",placeholder:"materials/body-sheen-color.jpg",value:t?.sheenColorMap?.path??"",onChange:w=>c(e,"sheenColorMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.sheenRoughness",label:"Roughness",value:t?.sheenRoughness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,sheenRoughness:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.sheenRoughnessMap.path",label:"Roughness map",placeholder:"materials/body-sheen-roughness.jpg",value:t?.sheenRoughnessMap?.path??"",onChange:w=>c(e,"sheenRoughnessMap",w)})]})}),z(ut,{panelKey:"anisotropy",requiredTier:M,title:"Anisotropy",tooltip:"Stretches reflections in one direction for brushed or fiber-like surfaces.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(ye,{path:"objectBindings[\u2026].style.material.anisotropy",label:"Intensity",value:t?.anisotropy,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,anisotropy:w}))}),z(Tn,{label:"Direction",value:$,options:["factor","texture"],onChange:H}),$==="factor"?z(ye,{path:"objectBindings[\u2026].style.material.anisotropyRotation",label:"Rotation",value:t?.anisotropyRotation,min:0,max:6.28,step:.01,onChange:w=>p(e,I=>({...I,anisotropyRotation:w}))}):z(Fe,{path:"objectBindings[\u2026].style.material.anisotropyMap.path",label:"Map",placeholder:"materials/body-anisotropy.jpg",value:t?.anisotropyMap?.path??"",onChange:w=>c(e,"anisotropyMap",w)})]})}),z(ut,{panelKey:"transmission",requiredTier:M,title:"Transmission and volume",tooltip:"Controls glass-like transmission and how light travels through volume.",toggleLabel:"Toggle Transmission and Volume",controls:G,children:Ae("div",{className:"bb-grid",children:[z(ye,{path:"objectBindings[\u2026].style.material.transmission",label:"Transmission",value:t?.transmission,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,transmission:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.transmissionMap.path",label:"Map",placeholder:"materials/body-transmission.jpg",value:t?.transmissionMap?.path??"",onChange:w=>c(e,"transmissionMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.thickness",label:"Thickness",value:t?.thickness,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,thickness:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.thicknessMap.path",label:"Thickness map",placeholder:"materials/body-thickness.jpg",value:t?.thicknessMap?.path??"",onChange:w=>c(e,"thicknessMap",w)}),z(Po,{path:"objectBindings[\u2026].style.material.attenuationColor",label:"Volume tint",value:t?.attenuationColor??"#ffffff",onChange:w=>p(e,I=>({...I,attenuationColor:w}))}),z(gp,{path:"objectBindings[\u2026].style.material.attenuationDistance",label:"Attenuation",value:t?.attenuationDistance,min:0,step:.01,placeholder:"Infinity when unset",onChange:w=>p(e,I=>({...I,attenuationDistance:w}))})]})}),z(ut,{panelKey:"faces",title:"Faces",tooltip:"Chooses which side of the mesh renders and how backfaces are handled.",controls:G,children:z("div",{className:"bb-grid",children:z(Tn,{path:"objectBindings[\u2026].style.material.side",label:"Side",value:t?.side??"front",options:yd,onChange:w=>p(e,I=>({...I,side:w}))})})}),N.length?Ae("div",{className:"se-listHeader se-listHeader--footer",ref:v,children:[Ae("button",{type:"button",className:"bb-button bb-button--ghost bb-button--small","aria-expanded":f,onClick:()=>u(w=>!w),children:[z(th,{size:13,"aria-hidden":"true"}),"Add layer"]}),f?z("div",{className:"se-addMenu se-addMenu--up",role:"menu","aria-label":"Add layer",children:N.map(w=>Ae("button",{type:"button",role:"menuitem",onClick:()=>A(w.key),children:[z("span",{children:w.label}),w.advanced&&M.locked?z(eh,{size:12,"aria-label":"Needs an upgrade"}):null]},w.key))}):null]}):null]})}import{useRef as rh,useState as ah}from"react";import{Ban as sh,ChevronDown as lh}from"lucide-react";var gr="default",Fa=[{id:gr,label:"Default",swatch:"transparent",material:{}},{id:"wood",label:"Wood",swatch:"#8b5a2b",material:{baseColor:"#8b5a2b",metalness:0,roughness:.75,reflectivity:.04}},{id:"brushed-metal",label:"Brushed Metal",swatch:"linear-gradient(135deg, #cfcfcf, #8a8a8a)",material:{baseColor:"#c8c8c8",metalness:1,roughness:.35}},{id:"chrome",label:"Polished Chrome",swatch:"linear-gradient(135deg, #ffffff, #9aa0a6)",material:{baseColor:"#e8e8e8",metalness:1,roughness:.05}},{id:"gold",label:"Gold",swatch:"linear-gradient(135deg, #ffe9a8, #c89b2c)",material:{baseColor:"#e6b325",metalness:1,roughness:.2}},{id:"copper",label:"Copper",swatch:"linear-gradient(135deg, #e3a576, #8a4a26)",material:{baseColor:"#b87333",metalness:1,roughness:.3}},{id:"glass",label:"Glass",swatch:"linear-gradient(135deg, rgba(255,255,255,0.9), rgba(180,210,230,0.4))",material:{baseColor:"#ffffff",metalness:0,roughness:.02,reflectivity:.5,opacity:1,transmission:1,thickness:.5,attenuationColor:"#ffffff",attenuationDistance:1}},{id:"frosted-glass",label:"Frosted Glass",swatch:"linear-gradient(135deg, rgba(255,255,255,0.85), rgba(210,225,235,0.6))",material:{baseColor:"#ffffff",metalness:0,roughness:.4,reflectivity:.3,opacity:1,transmission:.9,thickness:.5}},{id:"plastic-glossy",label:"Glossy Plastic",swatch:"#dadada",material:{baseColor:"#dadada",metalness:0,roughness:.25,reflectivity:.5,clearcoat:.3,clearcoatRoughness:.1}},{id:"plastic-matte",label:"Matte Plastic",swatch:"#9a9a9a",material:{baseColor:"#9a9a9a",metalness:0,roughness:.85,reflectivity:.04}},{id:"rubber",label:"Rubber",swatch:"#1a1a1a",material:{baseColor:"#1a1a1a",metalness:0,roughness:.9,reflectivity:.02}},{id:"fabric",label:"Fabric",swatch:"#9c8a6b",material:{baseColor:"#9c8a6b",metalness:0,roughness:.95,sheen:.4,sheenColor:"#ffffff",sheenRoughness:.6}},{id:"ceramic",label:"Ceramic",swatch:"#f5f5f0",material:{baseColor:"#f5f5f0",metalness:0,roughness:.15,clearcoat:.6,clearcoatRoughness:.1}},{id:"concrete",label:"Concrete",swatch:"#9b9b93",material:{baseColor:"#9b9b93",metalness:0,roughness:.95,reflectivity:.03}}],nh=Array.from(new Set(Fa.flatMap(e=>Object.keys(e.material)))),ih=Object.fromEntries(nh.map(e=>[e,void 0]));function vp(e){return e.id===gr?ih:e.material}import{jsx as Wo,jsxs as Ha}from"react/jsx-runtime";function yp({disabled:e,onApply:t}){let[i,a]=ah(!1),o=rh(null);return hn([o],()=>a(!1),i),Ha("div",{className:"se-field se-fieldInline bb-presetRow",ref:o,children:[Wo("span",{className:"se-fieldLabel",children:"Preset"}),Ha("button",{type:"button",className:"bb-presetButton",disabled:e,"aria-expanded":i,onClick:()=>a(n=>!n),children:[Wo("span",{children:"Apply a preset"}),Wo(lh,{size:12,"aria-hidden":"true"})]}),i?Wo("div",{className:"se-addMenu bb-presetMenu",role:"menu","aria-label":"Material presets",children:Fa.map(n=>Ha("button",{type:"button",role:"menuitem",onClick:()=>{a(!1),t(vp(n))},children:[Wo("span",{className:"bb-presetSwatch",style:{background:n.swatch},children:n.id===gr?Wo(sh,{size:10,"aria-hidden":"true"}):null}),Wo("span",{className:"bb-presetLabel",children:n.label})]},n.id))}):null]})}import{jsx as Rn,jsxs as $a}from"react/jsx-runtime";function wp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o,idError:n}){return Rn(Ye,{title:"Identity",open:i,onToggle:a,children:$a("div",{className:"bb-grid",children:[$a("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].modelObjectId",children:[Rn("label",{className:"bb-label",title:"The object's exact name in the model file. It can't be changed.",children:"Model object ID"}),Rn("input",{className:"bb-input bb-readonly",value:t.modelObjectId,readOnly:!0})]}),$a("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].id",children:[Rn("label",{className:"bb-label",children:"ID"}),Rn("input",{className:`bb-input ${n?"bb-input--error":""}`,value:t.id,onChange:d=>o(e,s=>({...s,id:d.target.value}))}),n?Rn("span",{className:"bb-status bb-status--error bb-fieldFull",children:n}):null]})]})})}import{useEffect as dh,useState as Sp}from"react";import{jsx as Ze,jsxs as Dt}from"react/jsx-runtime";function kp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o}){let[n,d]=Sp(t.group??""),[s,p]=Sp(t.tags?.join(", ")??"");dh(()=>{d(t.group??""),p(t.tags?.join(", ")??"")},[e,t.group,t.tags]);let c=()=>{o(e,h=>({...h,group:n.trim()||void 0}))},x=()=>{let h=[...new Set(s.split(",").map(g=>g.trim()).filter(Boolean))];o(e,g=>({...g,tags:h.length>0?h:void 0}))};return Dt(Ye,{title:"Basics",open:i,onToggle:a,children:[Dt("div",{className:"bb-grid",children:[Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Label"}),Ze("input",{className:"bb-input",value:t.label??"",onChange:h=>o(e,g=>({...g,label:h.target.value}))})]}),Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Type"}),Ze("input",{className:"bb-input",list:"binding-type-suggestions",value:t.type??"other",onChange:h=>o(e,g=>({...g,type:h.target.value}))}),Ze("datalist",{id:"binding-type-suggestions",children:Nd.map(h=>Ze("option",{value:h},h))})]}),Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Status"}),Ze("select",{className:"bb-select",value:t.status??"normal",onChange:h=>o(e,g=>({...g,status:h.target.value})),children:Ad.map(h=>Ze("option",{value:h,children:h},h))})]}),Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Group"}),Ze("input",{className:"bb-input",placeholder:"paint",value:n,onChange:h=>d(h.target.value),onBlur:c,onKeyDown:h=>{h.key==="Enter"&&h.currentTarget.blur()}})]}),Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Tags"}),Ze("input",{className:"bb-input",placeholder:"exterior, configurable",value:s,onChange:h=>p(h.target.value),onBlur:x,onKeyDown:h=>{h.key==="Enter"&&h.currentTarget.blur()}})]})]}),Dt("div",{className:"bb-checkboxRow",children:[Dt("label",{className:"bb-checkbox",children:[Ze("input",{type:"checkbox",checked:t.selectable!==!1,onChange:h=>o(e,g=>({...g,selectable:h.target.checked}))}),"Selectable"]}),Dt("label",{className:"bb-checkbox",children:[Ze("input",{type:"checkbox",checked:t.hoverable!==!1,onChange:h=>o(e,g=>({...g,hoverable:h.target.checked}))}),"Hoverable"]}),Dt("label",{className:"bb-checkbox",children:[Ze("input",{type:"checkbox",checked:t.visible!==!1,onChange:h=>o(e,g=>({...g,visible:h.target.checked}))}),"Visible"]})]})]})}import{useEffect as ch,useState as ph}from"react";import{Plus as uh,Trash2 as bh}from"lucide-react";import{Fragment as mh,jsx as He,jsxs as bt}from"react/jsx-runtime";var Cp=da.filter(e=>e.handling==="viewer"),gh=da.filter(e=>e.handling==="host");function Mp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o,takesImage:n=!0}){let[d,s]=ph(new Set);ch(()=>{s(new Set)},[e]);let p=t.actions??[],c=(g,C)=>o(e,M=>({...M,actions:(M.actions??[]).map((y,T)=>T===g?C(y):y)})),x=g=>{o(e,C=>({...C,actions:(C.actions??[]).filter((M,y)=>y!==g)})),s(C=>{let M=new Set;return C.forEach(y=>{y<g?M.add(y):y>g&&M.add(y-1)}),M})},h=(g,C)=>s(M=>{let y=new Set(M);return C?y.add(g):y.delete(g),y});return bt(Ye,{title:"Actions",open:i,onToggle:a,children:[He("div",{className:"bb-actionList",children:p.map((g,C)=>{let M=Yi(g.id),y=d.has(C)||!M,T=g.id.trim(),f=M?null:Wl(g.id),u=T.length>0&&p.some((v,m)=>m!==C&&v.id.trim()===T);return bt("div",{className:"bb-actionCard",children:[bt("div",{className:"rui-groupHeader",children:[bt("span",{children:["Action ",C+1]}),He("button",{type:"button",className:"se-iconButton",title:"Remove action","aria-label":`Remove action ${C+1}`,onClick:()=>x(C),children:He(bh,{size:13})})]}),bt("div",{className:"bb-actionGrid",children:[bt("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].actions[\u2026].id",children:[He("label",{className:"bb-label",children:"ID"}),bt("select",{className:"bb-select",value:y?Wi:g.id,onChange:v=>{let m=v.target.value;if(m===Wi){h(C,!0);return}h(C,!1);let N=Yi(m);c(C,A=>({...A,id:m,label:N&&ca(A.label)?N.label:A.label}))},children:[He("optgroup",{label:"Handled by the viewer",children:Cp.map(v=>He("option",{value:v.id,children:v.id},v.id))}),He("optgroup",{label:"Handled by your app",children:gh.map(v=>He("option",{value:v.id,children:v.id},v.id))}),He("option",{value:Wi,children:"Custom\u2026"})]})]}),y?bt("div",{className:"bb-field bb-field--row",children:[He("label",{className:"bb-label",children:"Custom ID"}),He("input",{className:"bb-input",value:g.id,placeholder:"open-datasheet",onChange:v=>{h(C,!0),c(C,m=>({...m,id:v.target.value}))}})]}):null,bt("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].actions[\u2026].label",children:[He("label",{className:"bb-label",children:"Label"}),He("input",{className:"bb-input",value:g.label,onChange:v=>c(C,m=>({...m,label:v.target.value}))})]}),M?.id==="change-material"&&!n?He("span",{className:"bb-note bb-note--warning",children:"This object has no texture coordinates, so an image picked here can't be placed on it, and the viewer says so. Change Color and Add Image work."}):M?He("span",{className:"bb-note",children:M.description}):T.length===0?He("span",{className:"bb-note bb-note--error",children:"An action ID is required, the button renders but can never be identified in onAction."}):bt("span",{className:"bb-note bb-note--warning",children:["Unrecognised ID, the viewer has no built-in behavior for it. Add declarative effects and execute them with useViewerActions, or handle it in onAction.",f?bt(mh,{children:[" Did you mean ",He("button",{type:"button",className:"bb-linkButton",onClick:()=>{h(C,!1);let v=Yi(f);c(C,m=>({...m,id:f,label:v&&ca(m.label)?v.label:m.label}))},children:f}),"?"]}):null]}),g.effects?.length?bt("span",{className:"bb-note",children:[g.effects.length," declarative effect",g.effects.length===1?"":"s",", execute with useViewerActions."]}):null,u?He("span",{className:"bb-note bb-note--warning",children:"Another action on this binding uses the same ID, they will render as two identical buttons."}):null]})]},C)})}),He(to,{children:bt("button",{type:"button",className:"bb-button",onClick:()=>{let g=Cp.find(C=>!p.some(M=>M.id===C.id));o(e,C=>({...C,actions:[...C.actions??[],{id:g?.id??"",label:g?.label??"New action",type:"command"}]})),g||h(p.length,!0)},children:[He(uh,{size:13,"aria-hidden":"true"}),"Add action"]})})]})}import{useRef as fh}from"react";import{Image as hh,ImagePlus as xh,Trash2 as vh,Type as Pp}from"lucide-react";import{Fragment as Tp,jsx as Ke,jsxs as gt}from"react/jsx-runtime";var Bp=()=>`decal-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;function Rp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o,placement:n,onPlacementChange:d,defaultSize:s,onImageFile:p,onNudge:c}){let{tier:x}=it(),h=fh(null),g=t.decals??[],C=n?.nodeKey===e?n:null,M=f=>o(e,u=>({...u,decals:f.length>0?f:void 0})),y=(f,u)=>M(g.map(v=>v.id===f?{...v,...u}:v)),T=f=>{f.image&&qn(f.image),C?.decal.id===f.id&&d(null),M(g.filter(u=>u.id!==f.id))};return gt(Ye,{title:"Decals",open:i,onToggle:a,tooltip:"Print a logo, image, or text on the selected object's surface.",children:[St(x,"decalsPerObject",g.length)?null:Ke(We,{requiredTier:Ho("decalsPerObject",g.length),feature:"More decals on this object"}),gt(Tp,{children:[gt("div",{className:"rui-actions",children:[gt("button",{type:"button",className:"bb-button",disabled:!St(x,"decalsPerObject",g.length),onClick:()=>h.current?.click(),children:[Ke(xh,{size:13,"aria-hidden":"true"})," Add image"]}),gt("button",{type:"button",className:"bb-button",disabled:!St(x,"decalsPerObject",g.length),onClick:()=>d({nodeKey:e,decal:{id:Bp(),text:"Your text",color:"#ffffff",size:s}}),children:[Ke(Pp,{size:13,"aria-hidden":"true"})," Add text"]}),Ke("input",{ref:h,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif,image/svg+xml",className:"bb-hiddenInput",onChange:f=>{let u=f.target.files?.[0];if(f.target.value="",!u)return;let v=gn(u);It(v,URL.createObjectURL(u)),p?.(v,u),d({nodeKey:e,decal:{id:Bp(),image:v,size:s}})}})]}),g.length===0&&!C?Ke("p",{className:"se-listEmpty",children:"No decals on this object yet."}):null,g.map(f=>gt("div",{className:"bb-decalCard",children:[gt("div",{className:"rui-groupHeader",children:[gt("span",{className:"rui-groupTitle",title:f.image??f.text,children:[f.image?Ke(hh,{size:13,"aria-hidden":"true"}):Ke(Pp,{size:13,"aria-hidden":"true"}),f.image??f.text]}),Ke("button",{type:"button",className:"se-iconButton",title:"Delete decal","aria-label":"Delete decal",onClick:()=>T(f),children:Ke(vh,{size:13})})]}),Ke(Yl,{onNudge:u=>c(f.id,u)}),gt("div",{className:"bb-grid",children:[f.image?null:gt(Tp,{children:[gt("div",{className:"bb-field bb-field--row",children:[Ke("label",{className:"bb-label",children:"Text"}),Ke("input",{className:"bb-input",value:f.text??"",onChange:u=>y(f.id,{text:u.target.value})})]}),Ke(Po,{label:"Color",variant:"input",value:f.color??"#ffffff",onChange:u=>y(f.id,{color:u})}),gt("div",{className:"bb-field bb-field--row",children:[Ke("label",{className:"bb-label",children:"Weight"}),gt("select",{className:"bb-select",value:f.fontWeight??"bold",onChange:u=>y(f.id,{fontWeight:u.target.value}),children:[Ke("option",{value:"bold",children:"Bold"}),Ke("option",{value:"normal",children:"Regular"})]})]})]}),Ke(ye,{label:"Size",value:Number(f.size.toFixed(4)),min:Number((s/20).toPrecision(2)),max:Number((s*6).toPrecision(2)),step:Number((s/50).toPrecision(1)),onChange:u=>u!==void 0&&u>0&&y(f.id,{size:u})}),Ke(ye,{label:"Rotation",value:Math.round((f.rotation??0)*180/Math.PI),min:-180,max:180,step:1,onChange:u=>y(f.id,{rotation:(u??0)*Math.PI/180})}),Ke(ye,{label:"Opacity",value:f.opacity??1,min:0,max:1,step:.05,onChange:u=>y(f.id,{opacity:u??1})})]})]},f.id))]})]})}import{MapPin as yh,Trash2 as wh}from"lucide-react";import{jsx as mt,jsxs as li}from"react/jsx-runtime";var Sh=e=>e.map(t=>t.toFixed(2)).join(", ");function Np({open:e,onToggle:t,cameraState:i,formattedCameraState:a,savedCameraPosition:o,onSaveCameraPosition:n,onGoToSavedCamera:d,onClearSavedCamera:s,onResetView:p,onFitScene:c}){let x=o?.position&&o?.target?o:null;return li(Ye,{title:"Saved view",open:e,onToggle:t,tooltip:"Stores the current camera for this object, so selecting it flies there.",children:[mt(xn,{label:"Camera",children:mt("code",{className:"rui-readout",children:i?a?.position:"Move the camera"})}),mt(xn,{label:"Looking at",children:mt("code",{className:"rui-readout",children:i?a?.target:"\u2013"})}),x?li("div",{className:"rui-listRow rui-listRow--saved",children:[li("span",{className:"rui-listRowMain",children:[mt("span",{className:"rui-listRowTitle",children:"Saved view"}),mt("code",{className:"rui-listRowMeta",children:Sh(x.position)})]}),li("span",{className:"rui-listRowActions rui-listRowActions--visible",children:[mt("button",{type:"button",className:"se-iconButton",onClick:d,title:"Fly to the saved view","aria-label":"Fly to the saved view",children:mt(yh,{size:13})}),mt("button",{type:"button",className:"se-iconButton",onClick:s,title:"Delete saved view","aria-label":"Delete saved view",children:mt(wh,{size:13})})]})]}):null,li(to,{children:[mt("button",{type:"button",className:"bb-button",onClick:n,disabled:!i,children:x?"Update view":"Save view"}),mt("button",{type:"button",className:"bb-button",onClick:p,children:"Reset camera"}),mt("button",{type:"button",className:"bb-button",onClick:c,children:"Fit scene"})]})]})}import{useLayoutEffect as kh,useRef as Ch,useState as Mh}from"react";import{RotateCcw as Ph}from"lucide-react";import{jsx as Qe,jsxs as Yo}from"react/jsx-runtime";var Op=["X","Y","Z"],Bh=.1,Th=.1,Ap=.01;function Ep(e){let t=e%360;return t<0?t+360:t}function Rh(e){return Ep(e*180/Math.PI)}function Nh(e){return e*Math.PI/180}function Ua({value:e,min:t=-1/0,max:i=1/0,step:a=.1,disabled:o=!1,onChange:n,formatValue:d=c=>Number(c.toFixed(3)),ariaLabel:s,className:p}){let c=d(e),[x,h]=Mh(String(c)),g=Ch(!1);return kh(()=>{g.current||h(String(c))},[c]),Qe("input",{type:"number",className:p,step:a,min:t===-1/0?void 0:t,max:i===1/0?void 0:i,value:x,disabled:o,"aria-label":s,onFocus:()=>{g.current=!0},onChange:C=>{let M=C.target.value;if(h(M),M===""||M==="-")return;let y=Number(M);if(Number.isFinite(y)){let T=Math.max(t,Math.min(i,y));n(T)}},onBlur:()=>{g.current=!1,h(String(d(e)))}})}function Ah({value:e,min:t=-1/0,max:i=1/0,step:a=.1,disabled:o=!1,onChange:n,formatValue:d=p=>Number(p.toFixed(3)),label:s}){return Qe("div",{className:"bb-transformAxesGrid",children:Op.map((p,c)=>Yo("div",{className:"bb-transformAxis",children:[Qe("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:p}),Qe("div",{className:"bb-transformAxisControl",children:Qe(Ua,{className:"se-numberInput bb-transformNumberInput",step:a,min:t,max:i,value:e[c],disabled:o,formatValue:d,ariaLabel:`${p} ${s?.toLowerCase()||""}`,onChange:x=>{let h=[...e];h[c]=x,n(h,c)}})})]},p))})}function jp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o,originalTransform:n,originalTransforms:d}){let s=t.transform?.rotation??n?.rotation??[0,0,0],p=t.transform?.position??n?.position??[0,0,0],c=n?.scale??[1,1,1],x=pa(t.transform?.scale??c,c),h=(f=e??"")=>d?.[f]??(f===e?n:null),g=(f,u)=>f.transform?.pivot??Ql(u?.pivotLocal??[0,0,0],f.transform?.rotation??u?.rotation??[0,0,0],f.transform?.scale??u?.scale??[1,1,1],u?.rotationOrder??"XYZ",f.transform?.shear),C=(f,u)=>{e&&o(e,(v,m)=>{let N=h(m),G=[...v.transform?.rotation??N?.rotation??[0,0,0]];return G[f]=Nh(Ep(u)),{...v,transform:{...v.transform,rotation:G,pivot:g(v,N)}}})},M=(f,u)=>{e&&o(e,(v,m)=>{let N=h(m),G=[...v.transform?.position??N?.position??[0,0,0]];return G[f]=u,{...v,transform:{...v.transform,position:G}}})},y=f=>{if(!e)return;let u=Math.max(Ap,f);o(e,(v,m)=>{let N=h(m),A=N?.scale??[1,1,1],G=v.transform?.scale??A,B=pa(G,A),P=B>0?G:A,$=u/(B||1);return{...v,transform:{...v.transform,scale:P.map(H=>H*$),pivot:g(v,N)}}})},T=()=>{!e||!n||o(e,f=>{let u={...f.transform};return delete u.position,delete u.rotation,delete u.scale,delete u.pivot,delete u.shear,{...f,transform:Object.keys(u).length>0?u:void 0}})};return Yo(Ye,{title:"Transform",open:i,onToggle:a,tooltip:"Rotation and scale keep the object's visible center fixed. Scale preserves its proportions.",children:[Yo("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.rotation",children:[Qe("span",{className:"se-fieldLabel",children:"Rotation"}),Qe("div",{className:"bb-transformAxesGrid",children:Op.map((f,u)=>{let v=Math.round(Rh(s[u]));return Yo("div",{className:"bb-transformAxis",children:[Qe("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:f}),Qe("div",{className:"bb-transformAxisControl",children:Qe(Ua,{className:"se-numberInput bb-transformNumberInput",step:1,min:0,max:359,value:v,disabled:!e,formatValue:m=>Math.round(m),ariaLabel:`${f} rotation in degrees`,onChange:m=>C(u,m)})})]},f)})})]}),Yo("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.position",children:[Qe("span",{className:"se-fieldLabel",children:"Position"}),Qe(Ah,{value:p,min:-1/0,max:1/0,step:Bh,disabled:!e,label:"position",onChange:(f,u)=>M(u,f[u])})]}),Yo("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.scale",children:[Qe("span",{className:"se-fieldLabel",children:"Scale"}),Qe(Ua,{className:"se-numberInput bb-transformNumberInput",step:Th,min:Ap,value:x,disabled:!e,formatValue:f=>Number(f.toFixed(2)),ariaLabel:"Uniform scale factor",onChange:y})]}),Qe(to,{children:Yo("button",{type:"button",className:"bb-button",disabled:!e||!n,onClick:T,title:"Restore this object's position, rotation, and scale to what they were in the original model",children:[Qe(Ph,{size:13,"aria-hidden":"true"}),"Restore original"]})})]})}import{memo as Wh}from"react";import{useEffect as Dp,useId as Oh,useLayoutEffect as Ka,useMemo as Nn,useRef as di,useState as An}from"react";import{Box as Eh,ChevronDown as jh,ChevronRight as Ih,ChevronsDownUp as zh,ChevronsUpDown as Lh,Focus as Dh,Folder as Fh,Lightbulb as Hh,ListChecks as $h,Trash2 as Uh}from"lucide-react";function Ip(e,t){let i=new Map(Object.entries(t).filter(([,d])=>!d.removed).map(([d,s])=>[s.modelObjectId??d,d])),a=new Set,o=new Map;for(let d of e){let s=d.objectId?i.get(d.objectId):void 0;s&&a.add(s),o.set(d.id,{id:d.id,name:d.name,key:s,children:[],keys:[]})}let n=[];for(let d of e){let s=o.get(d.id);((d.parentId?o.get(d.parentId):void 0)?.children??n).push(s)}for(let[d,s]of Object.entries(t))!s.removed&&!a.has(d)&&n.push({id:`binding:${d}`,name:s.modelObjectId??d,key:d,children:[],keys:[d]});for(let d=e.length-1;d>=0;d--){let s=o.get(e[d].id);s.children=s.children.filter(p=>p.keys.length),s.keys=[...s.key?[s.key]:[],...s.children.flatMap(p=>p.keys)]}return n.filter(d=>d.keys.length)}function zp(e,t,i){let a=i.trim().toLowerCase();if(!a)return e;let o=n=>{let d=n.key?t[n.key]:void 0;if([n.name,n.key,d?.label,d?.type,d?.group,...d?.tags??[]].join(" ").toLowerCase().includes(a))return n;let p=n.children.map(o).filter(c=>!!c);return p.length?{...n,key:void 0,children:p,keys:p.flatMap(c=>c.keys)}:null};return e.map(o).filter(n=>!!n)}function _a(e,t,i=!1){let a=[],o=e.slice().reverse().map(n=>({node:n,depth:0,parentId:null}));for(;o.length;){let n=o.pop();if(a.push(n),i||!t.has(n.node.id))for(let d=n.node.children.length-1;d>=0;d--)o.push({node:n.node.children[d],depth:n.depth+1,parentId:n.node.id})}return a}function Va(e,t){for(let i of e){if(i.key===t)return[];let a=Va(i.children,t);if(a)return[i.id,...a]}return null}function Lp(e,t,i,a,o){if(o.range){let n=i?a.indexOf(i):-1,d=a.indexOf(t);if(n>=0&&d>=0){let s=a.slice(Math.min(n,d),Math.max(n,d)+1);return[...new Set(o.additive?[...e,...s]:s)]}}return o.toggle||o.additive?e.includes(t)?e.filter(n=>n!==t):[...e,t]:[t]}import{jsx as ge,jsxs as ft}from"react/jsx-runtime";var _h=[],Vh=[],Kh=[],ao=24;function Gh({count:e,total:t,name:i,onChange:a}){let o=di(null);return Ka(()=>{o.current&&(o.current.indeterminate=e>0&&e<t)},[e,t]),ge("input",{ref:o,className:"bb-treeCheckbox",type:"checkbox","aria-label":`Select ${i}`,"aria-checked":e>0&&e<t?"mixed":e===t,checked:e===t&&t>0,onChange:a})}function mr({bindings:e,hierarchy:t=Vh,selectedItem:i,onSelect:a,onHover:o,fill:n,isolatedItem:d,onIsolate:s,multiSelectEnabled:p=!1,multiSelectedKeys:c=_h,onSetMultiSelected:x,selectionSets:h=Kh,onSelectionSetsChange:g,onToggleMultiSelect:C}){let[M,y]=An(""),[T,f]=An(()=>new Set),[u,v]=An(""),m=di(null),N=Nn(()=>Ip(t,e),[t,e]),A=Nn(()=>zp(N,e,M),[N,e,M]),G=Nn(()=>_a(A,T,!!M.trim()),[A,T,M]),B=Nn(()=>G.flatMap(({node:j})=>j.key?[j.key]:[]),[G]),P=Nn(()=>A.flatMap(j=>j.keys),[A]),$=di(null);Dp(()=>{if($.current===i)return;let j=i?Va(N,i):null;i&&!j||($.current=i,j?.length&&f(J=>{if(!j.some(Ce=>J.has(Ce)))return J;let L=new Set(J);return j.forEach(Ce=>L.delete(Ce)),L}))},[i,N]);let H=Nn(()=>new Set(p||c.length>0?c:i?[i]:[]),[p,c,i]),de=P.length>0&&P.every(j=>H.has(j)),_=j=>{let J=j.every(Ce=>H.has(Ce)),L=new Set(j);x?.(J?[...H].filter(Ce=>!L.has(Ce)):[...new Set([...H,...j])])},Q=j=>f(J=>{let L=new Set(J);return L.has(j)?L.delete(j):L.add(j),L}),w=(j,J)=>{let L=j.node.key;if(!L){Q(j.node.id);return}x&&(p||J.shiftKey||J.ctrlKey||J.metaKey)?x(Lp([...H],L,m.current??i,B,{range:J.shiftKey,additive:J.ctrlKey||J.metaKey,toggle:p&&!J.shiftKey})):a(L),J.shiftKey||(m.current=L)},I=j=>{let J=new Set(j.objectIds);return Object.keys(e).filter(L=>!e[L].removed&&J.has(e[L].modelObjectId??L))},he=St(it().tier,"selectionSets",h.length),Ne=()=>{let j=[...H].filter(J=>e[J]&&!e[J].removed);!j.length||!u.trim()||h.length>=128||!he||(g?.([...h,{id:crypto.randomUUID(),name:u.trim(),objectIds:j.map(J=>e[J].modelObjectId??J)}]),v(""))};return ft("section",{className:`bb-nodeList ${n?"bb-nodeList--fill":""}`,children:[ft("div",{className:"bb-outlinerHead",children:[ge("div",{className:"bb-search",children:ge("input",{className:"bb-input","aria-label":"Filter objects",placeholder:"Filter objects",value:M,onChange:j=>y(j.target.value)})}),C&&ge("button",{type:"button",className:`bb-treeIcon ${p?"bb-treeIcon--active":""}`,"aria-pressed":p,"aria-label":"Toggle multi-select",title:p?"Multi-select on: edits apply to every selected object":"Select multiple objects",onClick:C,children:ge($h,{size:14})}),ge("button",{type:"button",className:"bb-treeIcon","aria-label":"Expand all",title:"Expand all",onClick:()=>f(new Set),children:ge(Lh,{size:14})}),ge("button",{type:"button",className:"bb-treeIcon","aria-label":"Collapse all",title:"Collapse all",onClick:()=>f(new Set(_a(N,new Set,!0).filter(({node:j})=>j.children.length).map(({node:j})=>j.id))),children:ge(zh,{size:14})})]}),x&&M.trim()&&P.length>0&&ft("div",{className:"bb-selectionModeBar bb-selectionModeBar--matches",children:[ft("span",{children:[P.length," ",P.length===1?"match":"matches"]}),ge("button",{type:"button",className:"bb-button bb-button--small",onClick:()=>_(P),children:de?"Clear":"Select all"})]}),ge(qh,{rows:G,revealKey:i,bindings:e,selected:H,multiSelect:p,collapsed:T,searching:!!M.trim(),search:M,onSelect:w,onToggle:Q,onToggleKeys:x?_:void 0,onSelectAll:x?()=>x(P):void 0,onHover:o,isolatedItem:d,onIsolate:s}),g&&ft("details",{className:"bb-selectionSets",children:[ft("summary",{children:["Saved selections",h.length?` (${h.length})`:""]}),ft("div",{className:"bb-selectionSetCreate",children:[ge("input",{className:"bb-input","aria-label":"Selection name",placeholder:"Name this selection",maxLength:200,value:u,onChange:j=>v(j.target.value),onKeyDown:j=>{j.key==="Enter"&&(j.preventDefault(),Ne())}}),ge("button",{type:"button",className:"bb-button bb-button--ghost",disabled:!H.size||!u.trim()||h.length>=128||!he,title:he?void 0:"Saving more selections requires the Starter plan or higher.",onClick:Ne,children:"Save"})]}),!h.length&&ge("p",{children:"Select objects, then save the selection to reuse it."}),h.map(j=>{let J=I(j);return ft("div",{className:"bb-selectionSetRow",children:[ft("button",{type:"button",className:"bb-button bb-button--ghost",disabled:!J.length,title:J.length<j.objectIds.length?`${j.objectIds.length-J.length} objects unavailable`:void 0,onClick:()=>{y(""),f(new Set),x?.(J),m.current=J[0]??null},children:[j.name,ft("small",{children:[J.length," / ",j.objectIds.length]})]}),ge("button",{type:"button",className:"bb-treeIcon","aria-label":`Delete selection ${j.name}`,onClick:()=>g(h.filter(L=>L.id!==j.id)),children:ge(Uh,{size:14})})]},j.id)})]})]})}function qh({rows:e,revealKey:t,bindings:i,selected:a,multiSelect:o,collapsed:n,searching:d,search:s,onSelect:p,onToggle:c,onToggleKeys:x,onSelectAll:h,onHover:g,isolatedItem:C,onIsolate:M}){let y=di(null),[T,f]=An(400),[u,v]=An(0),[m,N]=An(0),A=Oh();Ka(()=>{let _=y.current;if(!_)return;let Q=new ResizeObserver(()=>f(_.clientHeight));return Q.observe(_),()=>Q.disconnect()},[]),Dp(()=>{y.current&&(y.current.scrollTop=0),v(0),N(0)},[s]);let G=_=>{_=Math.max(0,Math.min(e.length-1,_)),N(_);let Q=y.current;Q&&(_*ao<Q.scrollTop?Q.scrollTop=_*ao:(_+1)*ao>Q.scrollTop+Q.clientHeight&&(Q.scrollTop=(_+1)*ao-Q.clientHeight))},B=di(null);Ka(()=>{if(B.current===t)return;if(!t){B.current=null;return}let _=e.findIndex(({node:Q})=>Q.key===t);_<0||(B.current=t,G(_))});let P=_=>{let Q=e[Math.min(m,e.length-1)];if(Q){if((_.ctrlKey||_.metaKey)&&_.key.toLowerCase()==="a"){_.preventDefault(),_.stopPropagation(),h?.();return}if(["ArrowDown","ArrowUp","ArrowLeft","ArrowRight","Home","End","Enter"," "].includes(_.key)){if(_.preventDefault(),_.stopPropagation(),_.key==="ArrowDown"&&G(m+1),_.key==="ArrowUp"&&G(m-1),_.key==="Home"&&G(0),_.key==="End"&&G(e.length-1),_.key==="ArrowRight"&&Q.node.children.length&&(n.has(Q.node.id)?c(Q.node.id):G(m+1)),_.key==="ArrowLeft")if(Q.node.children.length&&!n.has(Q.node.id))c(Q.node.id);else{let w=e.findIndex(I=>I.node.id===Q.parentId);w>=0&&G(w)}(_.key==="Enter"||_.key===" ")&&(_.key===" "&&o&&!Q.node.key?x?.(Q.node.keys):p(Q,_))}}},$=Math.max(0,Math.min(e.length-1,Math.floor(u/ao))-5),H=Math.min(e.length,$+Math.ceil(T/ao)+12),de=Math.min(m,e.length-1);return ft("div",{ref:y,className:"bb-sceneTree",role:"tree","aria-label":"Scene hierarchy","aria-multiselectable":!!h,tabIndex:0,"aria-activedescendant":de>=$&&de<H?`${A}-${de}`:void 0,onKeyDown:P,onScroll:_=>v(_.currentTarget.scrollTop),children:[!e.length&&ge("p",{className:"bb-treeEmpty",children:"No matching objects."}),ge("div",{style:{height:e.length*ao,position:"relative"},children:e.slice($,H).map((_,Q)=>{let{node:w,depth:I}=_,he=$+Q,Ne=w.key?i[w.key]:void 0,j=w.keys.reduce((Ce,tn)=>Ce+Number(a.has(tn)),0),J=w.children.length?d||!n.has(w.id):void 0,L=w.key?a.has(w.key):j===w.keys.length;return ft("div",{id:`${A}-${he}`,role:"treeitem","aria-level":I+1,"aria-expanded":J,"aria-selected":L,className:`bb-treeRow${L?" bb-treeRow--selected":""}${w.key?" bb-treeRow--object":""}`,style:{top:he*ao,height:ao,paddingLeft:4+Math.min(I,10)*12},onFocus:()=>N(he),onMouseEnter:()=>g?.(w.key??null),onMouseLeave:()=>g?.(null),children:[w.children.length?ge("button",{type:"button",tabIndex:-1,className:"bb-treeIcon","aria-label":`${J?"Collapse":"Expand"} ${w.name}`,onClick:()=>c(w.id),children:J?ge(jh,{size:13}):ge(Ih,{size:13})}):ge("span",{className:"bb-treeSpacer"}),o&&x&&ge(Gh,{count:j,total:w.keys.length,name:w.name,onChange:()=>x(w.keys)}),ft("button",{type:"button",tabIndex:-1,className:"bb-treeNode",onClick:Ce=>{N(he),y.current?.focus({preventScroll:!0}),p(_,Ce)},children:[Ne?Ne.type==="light"?ge(Hh,{size:13,"aria-hidden":"true"}):ge(Eh,{size:13,"aria-hidden":"true"}):ge(Fh,{size:13,"aria-hidden":"true"}),ge("span",{title:Ne?`${Ne.type??"other"} \xB7 ${Ne.modelObjectId}`:void 0,children:Ne?.label||w.name}),Ne?null:ge("small",{children:w.keys.length})]}),w.key&&M&&ge("button",{type:"button",tabIndex:-1,className:"bb-treeIcon bb-treeIsolate","aria-label":`${C===w.key?"Show all":"Isolate"} ${w.name}`,"aria-pressed":C===w.key,onClick:()=>M(C===w.key?null:w.key),children:ge(Dh,{size:13})})]},w.id)})})]})}import{Fragment as Xh,jsx as Jo,jsxs as Ga}from"react/jsx-runtime";var qa=[],Fp=Wh(Yh);function Wa(e){let t=0;for(let i of Object.values(e))i.removed||(t+=1);return t}function Yh({bindings:e,selectedItem:t,onSelect:i,onHover:a,modelGroups:o,onSelectModel:n,isolatedItem:d=null,onIsolate:s,multiSelectEnabled:p=!1,onToggleMultiSelect:c,onExitMultiSelect:x,multiSelectedKeys:h=qa,onSetMultiSelected:g,hierarchy:C,selectionSets:M,onSelectionSetsChange:y}){let T=o&&o.length>=2?o:null,f=T?T.reduce((u,v)=>u+Wa(v.bindings),0):Wa(e);return Ga(Xh,{children:[p&&Ga("div",{className:"bb-selectionModeBar",children:[Ga("span",{children:[h.length," of ",f," selected"]}),Jo("button",{type:"button",className:"bb-button bb-button--small","aria-label":"Exit multi-select",onClick:x??c,children:"Done"})]}),T?Jo(Jh,{groups:T,selectedItem:t,onSelect:i,onHover:a,onSelectModel:n,isolatedItem:d,onIsolate:s,multiSelectEnabled:p,multiSelectedKeys:h,onSetMultiSelected:g,onToggleMultiSelect:c,hierarchy:C,selectionSets:M,onSelectionSetsChange:y}):Jo(mr,{bindings:e,selectedItem:t,onSelect:i,onHover:a,isolatedItem:d,onIsolate:s,multiSelectEnabled:p,multiSelectedKeys:h,onSetMultiSelected:g,onToggleMultiSelect:c,hierarchy:C,selectionSets:M,onSelectionSetsChange:y})]})}function Jh({groups:e,selectedItem:t,onSelect:i,onHover:a,onSelectModel:o,isolatedItem:n=null,onIsolate:d,multiSelectEnabled:s=!1,multiSelectedKeys:p=qa,onSetMultiSelected:c,onToggleMultiSelect:x,hierarchy:h,selectionSets:g,onSelectionSetsChange:C}){return Jo("section",{className:"bb-nodeList bb-nodeList--grouped",children:e.map(M=>{let y=M.isActive,T=Wa(M.bindings),f=`${M.label} (${T})${M.isActive?" \xB7 Active":""}`,u=y;return Jo("div",{className:`bb-groupItem ${u?"bb-groupItem--fill":""}`,children:Jo(Ye,{title:f,open:y,onToggle:()=>{o?.(M.url)},children:Jo(mr,{bindings:M.bindings,hierarchy:M.isActive?h:void 0,selectionSets:M.isActive?g:void 0,onSelectionSetsChange:M.isActive?C:void 0,selectedItem:t,onSelect:v=>{o?.(M.url),i(v)},onHover:a,fill:u,isolatedItem:M.isActive?n:null,onIsolate:M.isActive?d:void 0,multiSelectEnabled:M.isActive&&s,multiSelectedKeys:M.isActive?p:qa,onSetMultiSelected:M.isActive?c:void 0,onToggleMultiSelect:M.isActive?x:void 0})})},M.url)})})}import{jsx as Ya,jsxs as Zh}from"react/jsx-runtime";function Ja({title:e,label:t,open:i,onToggle:a,draft:o,error:n,example:d,onDraftChange:s,onCommit:p}){return Ya(Ye,{title:e,open:i,onToggle:a,children:Zh("div",{className:"rui-stack",children:[Ya("textarea",{className:"bb-textarea","aria-label":t,placeholder:d,value:o,onChange:c=>s(c.target.value),onBlur:p}),n?Ya("span",{className:"bb-note bb-note--error",children:n}):null]})})}import{useCallback as Pt}from"react";import{PropertyBinding as Up}from"three";import{PropertyBinding as Xa}from"three";function Hp(e){let t=new Map;return e.map(i=>{let a=(t.get(i)??0)+1;return t.set(i,a),a===1?i:`${i} (${a})`})}function Xo(e,t,i=[],a={},o=new Set(Object.keys(Ui(e).nodesById))){let n=new Map(Object.entries(t).filter(([,g])=>g.removed===!0).map(([g,C])=>[C.modelObjectId??g,C])),d=new Set(Object.entries(a).map(([g,C])=>C.modelObjectId??g)),s=i.filter(g=>g.loadState==="loading").map(g=>Xa.sanitizeNodeName(`${Gt(g.namePrefix)}_`)),p=Object.fromEntries(Object.entries(t).filter(([g,C])=>{let M=C.modelObjectId??g;return!d.has(M)&&(C.removed===!0||o.has(M)||s.some(y=>M.startsWith(y)))})),c=Object.fromEntries(Object.entries(a).map(([g,C])=>[g,n.get(C.modelObjectId??g)??C])),x={...p,...c},h=Object.keys(x);return h.length===Object.keys(t).length&&h.every(g=>x[g]===t[g])?t:x}function Gt(e){return e.replace(/\.[^./\\]+$/,"")}function Za(e,t,i={}){let a=Xa.sanitizeNodeName(Gt(e)).replace(/_/g,"-")||"Model",o=t.map(s=>Xa.sanitizeNodeName(Gt(s.namePrefix))),n=Object.entries(i).map(([s,p])=>p.modelObjectId??s),d=a;for(let s=2;;s++){let p=`${d}_`;if(!o.some(c=>c===d||c.startsWith(p))&&!n.some(c=>c.startsWith(p)))return d;d=`${a}-${s}`}}function On(e){e.resolved.cleanup()}function ci(e){e.resolved?.cleanup(),e.mergedModelSources.forEach(On)}function pi(e,t){let i=ad(e),a=Yn(i,Xi(e));if(t){let n=new Map(Object.values(t).map(d=>[d.modelObjectId,d]));for(let d of i){let s=n.get(d);s&&(a[d]=s)}}e.updateMatrixWorld(!0);let o={};for(let n of i){let d=Gn(e,n);if(!d){o[n]={position:[0,0,0],rotation:[0,0,0],scale:[1,1,1],pivotLocal:[0,0,0],rotationOrder:"XYZ"};continue}let s=Zl(d);o[n]={position:[d.position.x,d.position.y,d.position.z],rotation:[d.rotation.x,d.rotation.y,d.rotation.z],scale:[d.scale.x,d.scale.y,d.scale.z],pivotLocal:[s.x,s.y,s.z],rotationOrder:d.rotation.order}}return{bindings:a,originalTransforms:o,nodeNames:i}}function Qh(e,t){let i=e;for(;i;){if(i===t)return!0;i=i.parent}return!1}function Qa(e,t){let i=e.parent??e,a=pi(i,t),o=a.nodeNames.filter(n=>{let d=Gn(i,n);return d?Qh(d,e):!1});return{bindings:Object.fromEntries(o.map(n=>[n,a.bindings[n]])),originalTransforms:Object.fromEntries(o.map(n=>[n,a.originalTransforms[n]])),nodeNames:o}}function fr(e,t=[]){let i={bindings:e,mergeSources:t};return{past:[],present:i,future:[],baseline:i,edits:0}}function _p(e,t){let i=t(e.present),a=e.past.map(t),o=e.future.map(t),n=t(e.baseline);return i===e.present&&n===e.baseline&&a.every((d,s)=>d===e.past[s])&&o.every((d,s)=>d===e.future[s])?e:{...e,present:i,past:a,future:o,baseline:n}}function Vp(e,t,i,a={}){return _p(e,o=>{if(!o.mergeSources.some(s=>s.url===t))return o;let n=new Map(Object.entries(o.bindings).map(([s,p])=>[p.modelObjectId??s,p])),d={...o.bindings};for(let[s,p]of Object.entries(a))d[s]=n.get(p.modelObjectId??s)??p;return{bindings:d,mergeSources:o.mergeSources.map(s=>s.url===t?{...s,...i}:s)}})}function es(e,t){let i=e.mergeSources.find(n=>n.url===t);if(!i)return e;let a=new Set(i.nodeNames),o=Up.sanitizeNodeName(`${Gt(i.namePrefix)}_`);return{mergeSources:e.mergeSources.filter(n=>n.url!==t),bindings:Object.fromEntries(Object.entries(e.bindings).filter(([n,d])=>{let s=d.modelObjectId??n;return!a.has(s)&&!a.has(n)&&!s.startsWith(o)}))}}function ts(e,t){let i=io(e.bindingHistory??fr(e.bindings,e.mergedModelSources),{type:"set",updater:t,track:!0,coalesce:!1});return{...e,bindings:i.present.bindings,mergedModelSources:i.present.mergeSources,bindingHistory:i}}function os(e,t,i,a){let o=Vp(e.bindingHistory??fr(e.bindings,e.mergedModelSources),t,i,a);return{...e,bindings:o.present.bindings,mergedModelSources:o.present.mergeSources,bindingHistory:o}}function Kp(e,t){let i=e.bindingHistory??fr(e.bindings,e.mergedModelSources),o=[i.present,...i.past,...i.future].flatMap(s=>s.mergeSources).map(s=>Up.sanitizeNodeName(`${Gt(s.namePrefix)}_`)),n=Object.fromEntries(Object.entries(t).filter(([s,p])=>!o.some(c=>(p.modelObjectId??s).startsWith(c)))),d=_p(i,s=>({...s,bindings:{...n,...s.bindings}}));return{...e,bindings:d.present.bindings,bindingHistory:d}}function $p(e,t){let i=new Set(t.mergeSources.map(a=>a.url));return{...e,present:{...e.present,mergeSources:e.present.mergeSources.map(a=>i.has(a.url)?a:{...a,loadState:"loading"})}}}function Gp(e,t=[]){let i=ti({bindings:e,mergeSources:t}),{setValue:a,setValueAsStep:o,updateHistory:n,restoreSnapshot:d}=i,s=Pt(v=>a(m=>{let N=typeof v=="function"?v(m.bindings):v;return N===m.bindings?m:{...m,bindings:N}}),[a]),p=Pt(v=>o(m=>{let N=typeof v=="function"?v(m.bindings):v;return N===m.bindings?m:{...m,bindings:N}}),[o]),c=Pt(v=>n(m=>{let N=typeof v=="function"?v(m.present.bindings):v;if(N===m.present.bindings)return m;let A={...m.present,bindings:N};return{...m,present:A,baseline:m.edits===0?A:m.baseline}}),[n]),x=Pt(v=>n(m=>{let N=typeof v=="function"?v(m.present.mergeSources):v,A={...m.present,mergeSources:N};return{...m,present:A,baseline:m.edits===0?A:m.baseline}}),[n]),h=Pt(v=>o(m=>({...m,mergeSources:[...m.mergeSources,typeof v=="function"?v(m):v]})),[o]),g=Pt(v=>o(m=>es(m,v)),[o]),C=Pt((v,m,N)=>{n(A=>Vp(A,v,m,N))},[n]),M=Pt(()=>d(v=>{let m=io(v,{type:"undo"});return m===v?v:$p(m,v.present)}),[d]),y=Pt(()=>d(v=>{let m=io(v,{type:"redo"});return m===v?v:$p(m,v.present)}),[d]),T=Pt((v,m)=>d(N=>io(N,{type:"reset",value:{bindings:v,mergeSources:N.present.mergeSources},track:m?.asEdit??!1})),[d]),f=Pt(()=>d(v=>io(v,{type:"reset",value:v.present,track:!1})),[d]),u=Pt(v=>d({...v.bindingHistory??fr(v.bindings,v.mergedModelSources),present:{bindings:v.bindings,mergeSources:v.mergedModelSources}}),[d]);return{value:i.value.bindings,baseline:i.baseline.bindings,mergeSources:i.value.mergeSources,snapshot:i.snapshot,edits:i.edits,canUndo:i.canUndo,canRedo:i.canRedo,setValue:s,setValueAsStep:p,setValueUntracked:c,setMergeSourcesUntracked:x,addMerge:h,removeMerge:g,hydrateMerge:C,undo:M,redo:y,reset:T,clearHistory:f,restoreModel:u}}import{useEffect as qp,useRef as ex}from"react";function Wp(e,t,{modelUrl:i,modelSourceRef:a,uploadedFilesRef:o}={}){let n=ex(new Map);qp(()=>{let d=new Map,s=x=>{for(let h of[x.present,...x.past,...x.future])h.mergeSources.forEach(g=>d.set(g.url,g))};s(e);for(let x of t)x.bindingHistory&&s(x.bindingHistory),x.mergedModelSources.forEach(h=>d.set(h.url,h));for(let[x,h]of n.current)d.has(x)||h.resolved.cleanup();n.current=d;let p=new Set,c=x=>{x?.kind==="file"&&p.add(x.key)};i&&c(a?.current?.model),t.forEach(x=>c(x.sessionModel)),d.forEach(x=>c(x.sessionModel));for(let x of o?.current.keys()??[])p.has(x)||o?.current.delete(x)},[e,t,i,a,o]),qp(()=>()=>{n.current.forEach(d=>d.resolved.cleanup()),n.current.clear(),o?.current.clear()},[o])}import{useCallback as tx,useEffect as ns,useRef as ox}from"react";var nx=500;function Yp({composition:e,autosaveEnabled:t,hasEdits:i,modelUrl:a,bindings:o,sceneConfig:n,parkedModels:d,mergedModelSources:s,modelOrder:p,onTextureUpload:c,modelSourceRef:x,pendingLoadRef:h,storedModelKeysRef:g,uploadedFilesRef:C,pendingAutosaveRef:M,autosaveFailureShownRef:y,setStatusMessage:T,setStatusTone:f}){let u=ox(0),v=tx(async(m,N)=>{if(c)return c(m,N);let A=URL.createObjectURL(m);if(t)try{await wn(A,m)}catch(G){console.warn("[BindingBuilder] Could not store texture file for autosave:",G)}return A},[c,t]);return ns(()=>{if(!t||!i){M.current=null;return}let m=x.current;if(a&&!m){M.current=null;return}let N=a,A=()=>{if(M.current!==A||h.current)return;M.current=null;let B=++u.current,P=j=>{console.warn("[BindingBuilder] Autosave failed:",j),!y.current&&(y.current=!0,T("Couldn't autosave this session \u2014 the browser refused to store it, possibly for lack of space. Export your work to keep it."),f("error"))};if(!N||!m){g.current.clear(),$d().then(()=>{B===u.current&&(y.current=!1)}).catch(P);return}let{model:$}=m,H=[],de=new Set,_=j=>{if(!j||j.kind!=="file"||(de.add(j.key),g.current.has(j.key)))return;let J=C.current.get(j.key);J&&H.push({key:j.key,file:J})};_($),d.forEach(j=>{_(j.sessionModel),j.mergedModelSources.forEach(J=>_(J.sessionModel))}),s.forEach(j=>_(j.sessionModel)),g.current=new Set([...g.current].filter(j=>de.has(j)));let Q=j=>({model:j.sessionModel,namePrefix:j.namePrefix}),w=d.filter(j=>!!j.sessionModel).map(j=>({model:j.sessionModel,bindings:j.bindings,originalTransforms:j.originalTransforms,modelSettings:j.modelSettings,mergeModels:j.mergedModelSources.map(Q)})),I=s.map(Q),he=new Map;he.set(N,$),d.forEach(j=>{j.sessionModel&&he.set(j.url,j.sessionModel)});let Ne=p.map(j=>{let J=he.get(j);return J?Ut(J):null}).filter(j=>j!==null);Fd({model:$,composition:e,bindings:o,sceneConfig:n,parkedModels:w,mergeModels:I,modelOrder:Ne},H).then(()=>{B===u.current&&(g.current=de,y.current=!1)}).catch(P)};if(M.current=A,!N){A();return}let G=window.setTimeout(A,nx);return()=>window.clearTimeout(G)},[e,t,i,a,o,n,d,s,p]),ns(()=>{if(!t)return;let m=()=>M.current?.(),N=()=>{document.visibilityState==="hidden"&&m()};return window.addEventListener("pagehide",m),document.addEventListener("visibilitychange",N),()=>{window.removeEventListener("pagehide",m),document.removeEventListener("visibilitychange",N),m()}},[t]),ns(()=>{if(!t||!a||!i)return;let m=N=>{M.current?.(),N.preventDefault(),N.returnValue=""};return window.addEventListener("beforeunload",m),()=>window.removeEventListener("beforeunload",m)},[t,a,i]),{handleTextureUpload:v}}import{useCallback as is,useEffect as ix,useRef as Zo}from"react";var rs=640,as=360,rx=.82,ax=4e3,sx=2*6e4,Jp=1e3,lx=6e4;function dx({now:e,lastActivityAt:t,lastCaptureAt:i,ready:a,loadingTiles:o}){if(!a)return Jp;let n=e-t;return o&&n<lx?Jp:Math.max(ax-n,sx-(e-i),0)}async function cx(e){let t=new Image;t.src=e,await t.decode();let i=document.createElement("canvas");i.width=rs,i.height=as;let a=Math.max(rs/t.naturalWidth,as/t.naturalHeight),o=t.naturalWidth*a,n=t.naturalHeight*a,d=i.getContext("2d");if(!d)throw new Error("No 2D canvas to draw the thumbnail on.");return d.imageSmoothingQuality="high",d.drawImage(t,(rs-o)/2,(as-n)/2,o,n),new Promise((s,p)=>{i.toBlob(c=>c?s(c):p(new Error("Could not encode the thumbnail.")),"image/jpeg",rx)})}function Xp({onCapture:e,hasThumbnail:t,viewerRef:i,isModelLoading:a}){let o=Zo(e);o.current=e;let n=Zo(a);n.current=a;let d=Zo(!1),s=Zo(!1),p=Zo(null),c=Zo(0),x=Zo(Number.NEGATIVE_INFINITY),h=is(()=>{if(!o.current||!d.current||s.current||p.current!==null)return;let y=i.current,T=Date.now(),f=dx({now:T,lastActivityAt:c.current,lastCaptureAt:x.current,ready:!!y&&!n.current()&&document.visibilityState==="visible",loadingTiles:y?.isLoadingTiles()??!1});if(f>0){p.current=window.setTimeout(()=>{p.current=null,h()},f);return}s.current=!0,d.current=!1,x.current=T,y.captureImage({type:"image/jpeg",quality:.92}).then(cx).then(u=>o.current?.(u)).catch(u=>{d.current=!0,console.warn("[react-immersive] Could not update the project thumbnail.",u)}).finally(()=>{s.current=!1,h()})},[i]),g=is(()=>{c.current=Date.now()},[]),C=is(()=>{g(),d.current=!0,h()},[g,h]),M=!!e;return ix(()=>{if(!M)return;c.current=Date.now(),t||(d.current=!0),h();let y=["pointermove","pointerdown","keydown","wheel"];for(let T of y)window.addEventListener(T,g,{passive:!0,capture:!0});return()=>{for(let T of y)window.removeEventListener(T,g,{capture:!0});p.current!==null&&window.clearTimeout(p.current),p.current=null}},[M,t,g,h]),{markThumbnailOutdated:C,noteThumbnailActivity:g}}import{useLayoutEffect as px}from"react";function Zp({bindings:e,multiSelectMode:t,selectedItem:i,multiSelectedKeys:a,setSelectedItem:o,setMultiSelectedKeys:n}){px(()=>{let d=p=>!!(e[p]&&!e[p].removed),s=a.filter(d);s.length!==a.length&&n(s),i&&(!d(i)||t&&!s.includes(i))&&o(t?s[s.length-1]??null:null)},[e,t,i,a,o,n])}import{useCallback as Bo,useReducer as ux}from"react";var ls={selectedItem:null,keys:[],checkboxMode:!1},ss=(e,t)=>typeof e=="function"?e(t):e;function bx(e,t){if(t.type==="primary"){let p=ss(t.value,e.selectedItem);return p===e.selectedItem?e:{...e,selectedItem:p}}if(t.type==="keys"){let p=ss(t.value,e.keys);return p===e.keys?e:{...e,keys:p}}if(t.type==="mode"){let p=ss(t.value,e.checkboxMode);return p===e.checkboxMode?e:{...e,checkboxMode:p}}if(t.type==="clear")return ls;if(t.type==="exitMode"||t.type==="toggleMode"&&e.checkboxMode)return{...e,checkboxMode:!1,keys:[]};if(t.type==="toggleMode")return{...e,checkboxMode:!0,keys:e.keys.length?e.keys:e.selectedItem?[e.selectedItem]:[]};if(t.type==="selection"){let p=[...new Set(t.keys)];return{...e,keys:p,selectedItem:e.selectedItem&&p.includes(e.selectedItem)?e.selectedItem:p[p.length-1]??null}}if(t.type!=="select")return e;let{key:i,modifiers:a}=t;if(!i)return e.checkboxMode?e:ls;if(!e.checkboxMode&&!a.shiftKey&&!a.ctrlKey&&!a.metaKey)return{...e,selectedItem:i,keys:[]};let o=e.keys.length?e.keys:e.selectedItem?[e.selectedItem]:[],n=a.shiftKey&&!a.ctrlKey&&!a.metaKey,d=o.includes(i)&&!n,s=d?o.filter(p=>p!==i):[...new Set([...o,i])];return{...e,keys:s,selectedItem:d?e.selectedItem&&s.includes(e.selectedItem)?e.selectedItem:s[s.length-1]??null:i}}function Qp(){let[e,t]=ux(bx,ls),i=Bo(x=>t({type:"primary",value:x}),[]),a=Bo(x=>t({type:"keys",value:x}),[]),o=Bo(x=>t({type:"mode",value:x}),[]),n=Bo(x=>t({type:"selection",keys:x}),[]),d=Bo((x,h={})=>t({type:"select",key:x,modifiers:h}),[]),s=Bo(()=>t({type:"toggleMode"}),[]),p=Bo(()=>t({type:"exitMode"}),[]),c=Bo(()=>t({type:"clear"}),[]);return{selectedItem:e.selectedItem,multiSelectedKeys:e.keys,multiSelectMode:e.checkboxMode,groupSelectionActive:e.checkboxMode||e.keys.length>1,setSelectedItem:i,setMultiSelectedKeys:a,setMultiSelectMode:o,setSelection:n,selectObject:d,toggleMultiSelect:s,exitMultiSelect:p,clearSelection:c}}import{useCallback as eu,useEffect as gx,useState as mx}from"react";function tu(e,t){let[i,a]=mx(!1),o=e>0||t>0,n=eu(()=>a(!0),[]),d=eu(()=>a(!1),[]);return gx(()=>{o&&n()},[o,n]),{hasEdits:i||o,markSessionEdited:n,resetSessionEdits:d}}import{useEffect as ou,useReducer as fx,useRef as nu}from"react";function iu({enabled:e=!0,modelUrl:t,bindings:i,mergeSources:a,parkedModels:o,scenesRef:n,sceneRevision:d,setBindings:s,setParkedModels:p}){let[c,x]=fx(C=>C+1,0),h=nu(new WeakMap),g=nu(new WeakMap);ou(()=>{if(!e)return;let C=[t,...o.map(T=>T.url)],M=new Set(C.flatMap(T=>{let f=T?n.current.get(T):void 0;return f?[f]:[]})),y=T=>{T.target&&h.current.delete(T.target),x()};for(let T of M)T.addEventListener("childadded",y),T.addEventListener("childremoved",y);return()=>{for(let T of M)T.removeEventListener("childadded",y),T.removeEventListener("childremoved",y)}},[e,t,o,n,d]),ou(()=>{if(!e)return;let C=T=>{let f=h.current.get(T);return f||(f=new Set(Object.keys(Ui(T).nodesById)),h.current.set(T,f)),f},M=(T,f)=>{let u=C(T),v=g.current.get(T)??new Set;g.current.set(T,v);for(let[m,N]of Object.entries(f))N.removed&&v.add(N.modelObjectId??m);for(let m of v)u.has(m)&&v.delete(m);return v.size?new Set([...u,...v]):u},y=t?n.current.get(t):void 0;if(y){let T=M(y,i);s(f=>Xo(y,f,a,{},T))}p(T=>{let f=!1,u=T.map(v=>{let m=n.current.get(v.url);if(!m)return v;let N=Xo(m,v.bindings,v.mergedModelSources,{},M(m,v.bindings));return N===v.bindings?v:(f=!0,{...v,bindings:N})});return f?u:T})},[e,t,i,a,o,n,d,c,s,p])}import{useEffect as hx,useMemo as xx,useReducer as vx}from"react";function ru({modelUrl:e,scenesRef:t,sceneRevision:i,streaming:a=!1}){let o=e?t.current.get(e):void 0,[n,d]=vx(s=>s+1,0);return hx(()=>{if(!o||a)return;let s=()=>d();return o.addEventListener("childadded",s),o.addEventListener("childremoved",s),()=>{o.removeEventListener("childadded",s),o.removeEventListener("childremoved",s)}},[o,a]),xx(()=>({materialVariantGroups:o?_l(o):[],objectsWithoutUvs:o&&!a?Xi(o):new Set,hierarchy:o&&!a?Sd(o):[]}),[o,i,n,a])}import{AlertTriangle as yx,Box as wx,History as Sx,Trash2 as kx,Upload as Cx}from"lucide-react";import{useId as au,useState as Mx}from"react";import{Fragment as ui,jsx as pe,jsxs as $e}from"react/jsx-runtime";function Px(e){let t=new Date(e);return t.toDateString()===new Date().toDateString()?`today at ${t.toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}`:t.toLocaleString([],{dateStyle:"medium",timeStyle:"short"})}var ds=pe(yx,{size:15,"aria-hidden":"true"});function Ft({variant:e,...t}){return pe("button",{type:"button",className:`bb-dialogButton ${e?`bb-dialogButton--${e}`:""}`,...t})}function su({target:e,onCancel:t,onConfirm:i}){return $e(vn,{title:`Reset ${e==="bindings"?"object changes":e==="assets"?"asset placements":"scene settings"}?`,icon:ds,onCancel:t,footer:$e(ui,{children:[pe(Ft,{onClick:t,children:"Cancel"}),pe(Ft,{variant:"danger",onClick:i,autoFocus:!0,children:"Reset"})]}),children:[pe("p",{children:e==="bindings"?"This removes your changes to object properties, groups, tags, transforms, materials, actions, saved views, metrics, and metadata.":e==="assets"?"This resets every asset's position, rotation, and scale, and the grid spacing. Which assets are in the scene, their names, visibility, and object edits stay.":"This restores camera, lighting, environment, background, animations, annotations, and every other scene setting to their defaults."}),pe("p",{children:e==="assets"?"You can undo this.":"You can't undo this."})]})}function lu({models:e,savedAt:t,onCancel:i,onConfirm:a}){return $e(vn,{title:"Restore last session",icon:pe(Sx,{size:15,className:"bb-dialogIconNeutral","aria-hidden":"true"}),onCancel:i,footer:$e(ui,{children:[pe(Ft,{onClick:i,children:"Cancel"}),pe(Ft,{variant:"primary",onClick:a,autoFocus:!0,children:"Restore"})]}),children:[$e("p",{children:["Saved ",Px(t),", with your bindings and scene settings."]}),pe("ul",{className:"bb-modelList","aria-label":"Saved models",children:e.map((o,n)=>$e("li",{className:"bb-modelRow",children:[pe(wx,{size:14,className:"bb-modelRowIcon","aria-hidden":"true"}),$e("span",{className:"bb-modelRowText",children:[pe("span",{className:"bb-modelRowName",title:o.name,children:o.name}),o.mergedCount>0?$e("small",{children:[o.mergedCount," merged ",o.mergedCount===1?"model":"models"]}):null]})]},n))})]})}function du({nodeLabel:e,count:t=1,onCancel:i,onConfirm:a}){let o=t>1;return $e(vn,{title:o?`Delete ${e}?`:"Delete this object?",icon:ds,onCancel:i,footer:$e(ui,{children:[pe(Ft,{onClick:i,children:"Cancel"}),pe(Ft,{variant:"danger",onClick:a,autoFocus:!0,children:"Delete"})]}),children:[o?null:pe("p",{children:pe("strong",{children:e})}),$e("p",{children:[o?"They leave":"It leaves"," the Outliner and the 3D view for every viewer, rather than being hidden as the Visible checkbox does. You can undo this."]})]})}function cu({destinations:e,onCancel:t,onChoose:i}){let[a,o]=Mx(e.find(s=>s.isActive)?.url??e[0]?.url??""),n=e.find(s=>s.url===a),d=au();return $e(vn,{title:"Add model",icon:pe(Cx,{size:15,"aria-hidden":"true"}),onCancel:t,footer:$e(ui,{children:[pe(Ft,{onClick:t,children:"Cancel"}),pe(Ft,{onClick:()=>i({mode:"separate"}),children:"Add as separate model"}),pe(Ft,{variant:"primary",disabled:!n,title:n?`Merge into ${n.name}`:void 0,onClick:()=>n&&i({mode:"merge",targetUrl:a}),children:"Merge into model"})]}),children:[pe("p",{children:"A separate model stays independent and has its own group in the Outliner. Merging adds its objects to the model you choose."}),pe("label",{htmlFor:d,children:"Merge into"}),pe("select",{id:d,value:a,onChange:s=>o(s.target.value),children:e.map(s=>$e("option",{value:s.url,children:[s.label,": ",s.name,s.isActive?" (active)":""]},s.url))})]})}function pu({options:e,onCancel:t,onRemoveModel:i,onRemoveMerge:a,onRemoveAll:o,permanent:n=!1}){let d=au();return $e(vn,{title:"Remove model",icon:ds,onCancel:t,footer:$e(ui,{children:[pe(Ft,{onClick:t,children:"Cancel"}),o?pe(Ft,{variant:"danger","aria-describedby":d,onClick:o,children:"Remove all models"}):null]}),children:[pe("p",{children:"Its bindings, transforms and anything merged into it go with it. The other models stay."}),pe("ul",{className:"bb-modelList","aria-label":"Models",children:e.map(s=>$e("li",{className:"bb-modelRow",children:[$e("span",{className:"bb-modelRowText",children:[pe("span",{className:"bb-modelRowName",title:s.label,children:s.label}),s.kind!=="model"?$e("small",{children:["Merged into ",s.ownerLabel]}):s.name!==s.label?pe("small",{title:s.name,children:s.name}):null]}),s.kind==="model"&&s.isActive?pe("span",{className:"bb-modelRowBadge",children:"Active"}):null,$e("button",{type:"button",className:"bb-removeRowButton","aria-label":`Remove ${s.label}`,onClick:()=>s.kind==="model"?i(s.url):a(s.url),children:[pe(kx,{size:13,"aria-hidden":"true"}),"Remove"]})]},s.url))}),pe("p",{id:d,children:n?"Removing a model removes it for everyone in this project and deletes its stored file unless another project uses it. You can't undo this.":"Removing all models also clears the session saved in this browser. You can't undo this, so export anything you want to keep first."})]})}import{strToU8 as Bx}from"fflate";function Tx(e){return(e.decals??[]).map(t=>t.image).filter(t=>!!t?.trim())}function Rx(e){let t=e.style?.material;return t?Object.values(t).filter(i=>!!i&&typeof i=="object"&&typeof i.path=="string"&&i.path.trim().length>0).map(i=>i.path):[]}async function uu(e){let t=new Set;for(let i of Object.values(e)){for(let a of Rx(i))t.add(a);for(let a of Tx(i))t.add(a)}return gu(t)}async function bu(e){let t=new Set,i=e.background?.imageUrl?.trim();return i&&t.add(i),gu(t)}async function gu(e){let t=[],i=[];return await Promise.all(Array.from(e).map(async a=>{let o=$t(a);if(o)try{let n=await fetch(o);if(!n.ok)throw new Error(String(n.status));t.push({path:a,blob:await n.blob()});return}catch{i.push(a);return}try{let n=await oo(a);n&&t.push({path:a,blob:n})}catch{}})),{assets:t,failedPaths:i}}async function bi(e,t,i,a,o){if(o.length===0){ip(e,t,i);return}let n={[e]:Bx(t)};for(let s of o)n[s.path]=new Uint8Array(await s.blob.arrayBuffer());let d=await Ji(n);fn(new Blob([d],{type:"application/zip"}),a)}async function hr(e){let t=e.background?.imageUrl?.trim();if(t)try{let i=await oo(t);i&&It(t,URL.createObjectURL(i))}catch(i){console.warn("[BindingBuilder] Could not rehydrate the background image:",i)}}async function Qo(e){return await Promise.all(Object.entries(e).map(async([t,i])=>{for(let o of i.decals??[])if(o.image)try{let n=await oo(o.image);n&&It(o.image,URL.createObjectURL(n))}catch(n){console.warn(`[BindingBuilder] Could not rehydrate a decal image on "${t}":`,n)}let a=i.style?.material;if(a)for(let o of Jl){let d=a[o]?.path;if(d)try{let s=await oo(d);if(!s){console.warn(`[BindingBuilder] No stored texture found for "${t}"'s ${o} ("${d}"). If this is meant to be an uploaded file rather than a hosted URL, it was uploaded before texture autosave existed (or this browser's storage was cleared) \u2014 re-upload it once so it's stored for future restores.`);continue}let p=URL.createObjectURL(s);It(d,p)}catch(s){console.warn(`[BindingBuilder] Could not rehydrate "${t}"'s ${o}:`,s)}}})),e}async function gi(e){if(!e)return;let t={};for(let i of e.definition.groups)for(let a of i.options)for(let[o,n]of(a.appearance??[]).entries())if(n.material){let d=JSON.stringify([i.id,a.id,o]);t[d]={id:d,modelObjectId:d,style:{material:n.material}}}await Qo(t)}async function mu(e){let t=new Set,i=new WeakSet;function a(o,n=0){if(!(!o||typeof o!="object"||i.has(o)||n>64)){i.add(o);for(let[d,s]of Object.entries(o))d!=="metadata"&&(d==="path"&&typeof s=="string"&&s?t.add(s):a(s,n+1))}}return a(e),await Promise.all([...t].map(async o=>{let n=await oo(o);n&&It(o,URL.createObjectURL(n))})),e}function fu({bindings:e,setBindings:t,sceneConfig:i,setSceneConfig:a,nodeKeys:o,sceneConfigInputRef:n,setIsExporting:d,setStatusMessage:s,setStatusTone:p}){let c=f=>h("bindings",()=>uu(e),u=>f==="json"?bi("objectBindings.json",ri(e),"application/json","objectBindings.zip",u):bi("objectBindings.ts",cr(e),"text/typescript","objectBindings-ts.zip",u)),x=f=>h("scene config",()=>bu(i),u=>f==="json"?bi("sceneConfig.json",pr(i),"application/json","sceneConfig.zip",u):bi("sceneConfig.ts",ur(i),"text/typescript","sceneConfig-ts.zip",u)),h=async(f,u,v)=>{d(!0);try{let{assets:m,failedPaths:N}=await u();await v(m),N.length>0?(s(`Exported, but ${N.length} uploaded image${N.length===1?"":"s"} couldn't be bundled: ${N.join(", ")}.`),p("error")):m.length>0&&(s(`Exported with ${m.length} uploaded image${m.length===1?"":"s"} bundled into the zip.`),p("success"))}catch(m){let N=m instanceof Error?m.message:"Unknown export error.";s(`Failed to export ${f}: ${N}`),p("error")}finally{d(!1)}},g=async f=>{if(!o.length){s("Load a model before importing bindings."),p("error");return}let u;try{u=JSON.parse(await f.text())}catch{s(`${f.name} is not valid JSON.`),p("error");return}if(u===null||typeof u!="object"||Array.isArray(u)){s("Expected a JSON object mapping object IDs to bindings."),p("error");return}let v=new Map;for(let P of Object.values(u))if(P!==null&&typeof P=="object"&&typeof P.id=="string"&&typeof P.type=="string"&&typeof P.modelObjectId=="string"){let $=P;v.set($.modelObjectId,$)}if(v.size===0){s(`${f.name} doesn't look like an exported bindings file.`),p("error");return}let m={...e},N={},A=0;for(let P of Object.keys(m)){let $=v.get(P);$&&(m[P]=$,N[P]=$,A++)}if(A===0){s(`None of the object IDs in ${f.name} match this model \u2014 nothing imported.`),p("error");return}let G=await Qo(N);Object.assign(m,G),t(m);let B=v.size-A;s(B>0?`Imported ${A} binding${A===1?"":"s"} from ${f.name} (${B} skipped \u2014 not in this model).`:`Imported ${A} binding${A===1?"":"s"} from ${f.name}.`),p("success")},C=async f=>{let u=f.target.files?.[0];u&&(await g(u),f.target.value="")},M=()=>{n.current?.click()},y=async f=>{let u;try{u=JSON.parse(await f.text())}catch{s(`${f.name} is not valid JSON.`),p("error");return}if(u===null||typeof u!="object"||Array.isArray(u)){s("Expected a JSON object with scene config sections."),p("error");return}let v=["model","camera","lighting","wireframe","shadows","environment","background","groundShadows","postProcessing","animations","annotations","cinematic","styleRules","section","measurements","selectionSets","product"],m=u;if(m.product!==void 0)try{m.product=Gi(m.product)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(m.section!==void 0)try{m.section=Vi(i.section,m.section)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(m.selectionSets!==void 0)try{m.selectionSets=mn(m.selectionSets)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(m.measurements!==void 0)try{m.measurements=Ki(m.measurements)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}let N=v.filter(A=>m[A]!==void 0);if(N.length===0){s(`${f.name} doesn't look like an exported scene config file.`),p("error");return}await gi(m.product),N.includes("background")&&m.background&&await hr({background:m.background}),a(A=>{let G={...A};for(let B of N)G[B]=B==="measurements"||B==="section"||B==="product"?m[B]:ei(A[B],m[B]);return G}),s(`Imported ${N.length} section${N.length===1?"":"s"} from ${f.name}.`),p("success")};return{handleExportBindings:c,handleExportSceneConfig:x,importBindingsFile:g,handleImportBindingsChange:C,openSceneConfigImportPicker:M,importSceneConfigFile:y,handleImportSceneConfigChange:async f=>{let u=f.target.files?.[0];u&&(await y(u),f.target.value="")}}}var cs={pbr:["texture","baseColor","metalness","metalnessMap","specularIntensity","specularIntensityMap","specularColor","specularColorMap","reflectivity"],roughness:["roughness","roughnessMap"],emission:["emissive","emissiveIntensity","emissiveMap"],opacity:["opacity","alphaMap","alphaTest","alphaHash","dithering","blendingMode"],normalBump:["normalMap","normalScale","flipNormalY","bumpMap","bumpScale"],displacement:["displacementMap","displacementScale","displacementBias"],ao:["aoMap","aoMapIntensity"],clearcoat:["clearcoat","clearcoatMap","clearcoatRoughness","clearcoatRoughnessMap","clearcoatNormalMap","clearcoatNormalScale","flipClearcoatNormalY"],sheen:["sheen","sheenColor","sheenColorMap","sheenRoughness","sheenRoughnessMap"],anisotropy:["anisotropy","anisotropyRotation","anisotropyMap"],transmission:["transmission","transmissionMap","thickness","thicknessMap","attenuationColor","attenuationDistance"],faces:["side"]},hu=Object.keys(cs);function xu(e){if(e==null)return!1;if(typeof e=="string")return e.trim().length>0;if(typeof e=="number")return Number.isFinite(e);if(typeof e=="boolean")return e;if(typeof e=="object"&&"path"in e){let t=e.path;return typeof t=="string"&&t.trim().length>0}return!1}function ps(e){if(e)return Object.values(e).some(xu)?e:void 0}function Bt(e,t){return e?cs[t].some(i=>xu(e[i])):!1}function us(e){return{pbr:Bt(e,"pbr"),roughness:Bt(e,"roughness"),emission:Bt(e,"emission"),opacity:Bt(e,"opacity"),normalBump:Bt(e,"normalBump"),displacement:Bt(e,"displacement"),ao:Bt(e,"ao"),clearcoat:Bt(e,"clearcoat"),sheen:Bt(e,"sheen"),anisotropy:Bt(e,"anisotropy"),transmission:Bt(e,"transmission"),faces:Bt(e,"faces")}}function bs(e,t){if(t)return{...e,style:{...e.style,material:t}};if(!e.style)return e;let{material:i,...a}=e.style;return{...e,style:Object.keys(a).length>0?a:void 0}}function vu(e,t){if(!e)return;let i={...e};for(let a of cs[t])delete i[a];return i}import{ChevronDown as Nx,ChevronUp as Ax}from"lucide-react";import{jsx as en,jsxs as yu}from"react/jsx-runtime";function wu({panel:e,tabs:t,tab:i,onTabChange:a,hasModel:o,onPointerDownCapture:n,children:d}){let s=e.open&&o;return yu("div",{className:`bb-dock ${s?"bb-dock--open":""}`,onPointerDownCapture:n,children:[s?en(ii,{orientation:"horizontal",label:"Resize timeline",onPointerDown:e.startResize,onKeyDown:e.onResizeKey}):null,yu("div",{className:"bb-tabs bb-dockBar",role:"tablist","aria-label":"Animation",children:[t.map(({id:p,label:c})=>en("button",{type:"button",role:"tab",disabled:!o,"aria-selected":e.open&&i===p,className:`bb-tab ${e.open&&i===p?"bb-tab--active":""}`,onClick:()=>{e.open&&i===p?e.setOpen(!1):(a(p),e.setOpen(!0))},children:c},p)),en("span",{className:"bb-topBarSpacer"}),en("button",{type:"button",className:"bb-toolButton bb-toolButton--small",disabled:!o,"aria-label":e.open?"Collapse timeline":"Expand timeline",onClick:()=>e.setOpen(!e.open),children:e.open?en(Nx,{size:14}):en(Ax,{size:14})})]}),s?en("div",{className:"bb-dockBody",style:{height:e.size},children:d}):null]})}import{Fragment as et,jsx as R,jsxs as ae}from"react/jsx-runtime";var Gx=ko(()=>import("./AnnotationsTab-OHRVWRKI.mjs")),qx=ko(()=>import("./AnimationsTab-NUJTEMZ5.mjs")),Wx=ko(()=>import("./SequencesTab-LWGOVQ6Y.mjs")),Yx=ko(()=>import("./CinematicTab-IJAY2BS6.mjs")),Jx=ko(()=>import("./ConfigureTab-UQRRATCY.mjs")),ku="/room.glb";function gs(){return`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function ms(e){return`Couldn't reload ${e} from your last session. It's still saved in this browser.`}function Xx({label:e,values:t,onChange:i}){let a=t.length>0&&t.every(Boolean),o=!a&&t.some(Boolean);return ae("label",{className:"bb-groupFlag",children:[R("input",{type:"checkbox",ref:n=>{n&&(n.indeterminate=o)},checked:a,onChange:n=>i(n.target.checked)}),e]})}var Zx=[{id:"outliner",label:"Outliner"},{id:"assets",label:"Assets"},{id:"annotations",label:"Annotations"},{id:"measure",label:"Measure"}],Qx=[{id:"sequences",label:"Sequences"},{id:"clips",label:"Clips"},{id:"cinematic",label:"Cinematic"}],Cu=[{id:"general",label:"General",group:!0},{id:"material",label:"Material",group:!0},{id:"decals",label:"Decals",group:!1},{id:"actions",label:"Actions",group:!1},{id:"data",label:"Data",group:!0}],Mu={bindings:"object",scene:"scene",assets:"asset"},ev=ae(et,{children:[R("kbd",{children:"G"})," Move ",R("kbd",{children:"R"})," Rotate ",R("kbd",{children:"T"})," Scale ",R("kbd",{children:"F"})," Frame"," ",R("kbd",{children:"?"})," Shortcuts"]});function Pu(e,t=!1){let i=e;return i?.tagName?i.isContentEditable||i.tagName==="TEXTAREA"||t&&i.tagName==="SELECT"?!0:i.tagName!=="INPUT"?!1:!["range","checkbox","radio","button","file","color"].includes(i.type):!1}function tv({topBarStart:e,configurePublish:t,licenseKey:i,licenseValidationUrl:a,arHandoff:o=!0,mobileHandoffUrl:n,dracoDecoderPath:d,ktx2TranscoderPath:s,meshopt:p,project:c,onProjectChange:x,projectChangeDebounceMs:h=350,onModelUpload:g,onTextureUpload:C,onThumbnailCapture:M,hasThumbnail:y=!1,onEditLeaseChange:T,allowModelChange:f=!0,hideLicenseCheckingOverlay:u=!1}){let v=ne(null),m=ne(null),N=ne(null),A=ne(null),G=ne(null),[B]=U(()=>c?wa(c):null),[P,$]=U(B?.url??null),[H,de]=U(()=>c?c.models.filter(r=>r!==B).map(ka):[]),[_,Q]=U(()=>c?c.models.map(r=>r.url):[]),[w,I]=U(B?.name??""),[he,Ne]=U(B),j=Ue(()=>c&&_.length>1&&he?.tilesetUrl?{...he,tilesetUrl:null}:he,[c,_.length,he]),J=ne(c?Ca(c):new Map),{selectedItem:L,setSelectedItem:Ce,multiSelectMode:tn,setMultiSelectMode:Bu,multiSelectedKeys:_e,setMultiSelectedKeys:xr,groupSelectionActive:Oe,selectObject:En,setSelection:fs,toggleMultiSelect:Tu,exitMultiSelect:hs,clearSelection:xs}=Qp(),vs=ne({mode:!1,keys:[]}),mi=ne({shiftKey:!1,ctrlKey:!1,metaKey:!1}),[jn,Ru]=U(null);vs.current={mode:Oe,keys:_e};let ie=Gp(B?.objectBindings??{}),q=ie.value,To=ie.setValue,fi=ne("free");Zp({bindings:q,multiSelectMode:Oe,selectedItem:L,multiSelectedKeys:_e,setSelectedItem:Ce,setMultiSelectedKeys:xr});let Ee=ie.mergeSources,so=ie.setMergeSourcesUntracked;ze(()=>{B?.mergeModels?.length&&so(Sn(B))},[B,so]);let[Me,qt]=U(!1),[hi,In]=U(null),Nu=Ue(()=>hi?{target:hi}:null,[hi]);ze(()=>{In(null)},[P]),ze(()=>{Bu(!1),xr([])},[P]);let[xi,lo]=U(null);ze(()=>lo(null),[L,P]),ze(()=>{Dr(null),Hr(null)},[P]);let[Au,Ro]=U(null),[ys,Ou]=U(!1),[vr,W]=U(""),[yr,X]=U("default"),[Eu,ws]=U(null),ju=Z(()=>ws(null),[]),[Ss,vi]=U("{}"),[ks,yi]=U("{}"),[Iu,wi]=U(null),[zu,Si]=U(null),[Lu,zn]=U(!1),co=dr("left",{size:296,min:220,max:480,edge:"right"}),Wt=dr("inspector",{size:320,min:300,max:560,edge:"left"}),wr=dr("dock",{size:300,min:160,max:640,edge:"top",open:!1}),[Tt,Sr]=U("outliner"),[ki,Cs]=U("sequences"),[Ms,Ps]=U("general"),[Bs,kr]=U(!1),[Cr,Du]=U(!0),[Fu,Mr]=U(!1),[Hu,Pr]=U(!1),[Ln,No]=U("bindings"),[Yt,Ts]=U({identity:!0,basics:!0,material:!0,decals:!0,actions:!0,camera:!1,transform:!0,metrics:!0,metadata:!0}),[$u,Uu]=U({pbr:!0,roughness:!0,emission:!1,opacity:!0,normalBump:!1,displacement:!1,ao:!1,clearcoat:!1,sheen:!1,anisotropy:!1,transmission:!1,faces:!1}),Jt=r=>Ts(l=>({...l,[r]:!l[r]})),_u=r=>Uu(l=>({...l,[r]:!l[r]})),[Ci,Rs]=U(null),[po,Br]=U(!1),[ht,on]=U("object"),[nn,Tr]=U("model"),[Ns,As]=U(null),[Os,Es]=U(!1),[js,Vu]=U(null),Is=co.setOpen,zs=Z(()=>{Is(!0),Sr("measure"),Es(!0)},[Is]),[Ku,Gu]=U("metalness"),[qu,Rr]=U(us()),Ls=ne(null),[Ds,Wu]=U(!1),[Nr,Yu]=U(!0),[Ar,Ju]=U(!0),[Xu,Fs]=U(!1),[Dn,Hs]=U(null),[Ao,Or]=U(null),[Zu,Er]=U(!1),Mi=ne(null),Pi=ne({modelUrl:P,modelName:w,modelOrder:_,parkedModels:H});Pi.current={modelUrl:P,modelName:w,modelOrder:_,parkedModels:H};let[Qu,rn]=U(!1),[uo,jr]=U(null),[Xt,Bi]=U("select"),eb=Xt==="move"||Xt==="rotate",tb=Xt==="scale",[$s,ob]=U("world"),xt=ne({}),Be=ti(c&&B?er(c.sceneConfig,B):fo),Ve=ti(c?Sa(c):Do),[Us,an]=U([]),rt=Ue(()=>({...Ve.value,placements:{...Object.fromEntries(Us.map(r=>[r,{deleted:!0}])),...Ve.value.placements}}),[Ve.value,Us]),[sn,ln]=U(!1),_s=ne(null),ee=Be.value,Rt=Be.setValue,nb=Z(r=>{let l=mn(r);Be.setValueAsStep(b=>({...b,selectionSets:l}))},[Be.setValueAsStep]),Ti=Be.setValueUntracked,Ir=Z(r=>{let l=Xe(ee,r.modelSettings);r.sceneHistory?Be.restoreSnapshot({...r.sceneHistory,present:l}):Be.reset(l)},[ee,Be.restoreSnapshot,Be.reset]),{hasEdits:ib,markSessionEdited:at,resetSessionEdits:zr}=tu(ie.edits,Be.edits+Ve.edits),[Oo,Vs]=U(!1),[rb,ab]=U(.5),[Lr,sb]=U(!0),[dn,Dr]=U(null),cn=dn??{bindings:ie.baseline,sceneConfig:Be.baseline},[Fr,lb]=U("modelObjectId"),[Ri,Hr]=U(null),Fn=Ue(()=>Oo?fd({objectBindings:cn.bindings,sceneConfig:cn.sceneConfig},{objectBindings:q,sceneConfig:ee},{matchBy:Fr}):null,[Oo,cn.bindings,cn.sceneConfig,q,ee,Fr]),Ks=Ue(()=>Fn&&Lr?{before:ga(Fn,"before",Ri),after:ga(Fn,"after",Ri)}:null,[Fn,Ri,Lr]),[Gs,$r]=U("orbit"),[db,qs]=U(!1),Ur=ne(void 0),_r=Z(()=>{qs(!0),clearTimeout(Ur.current),Ur.current=setTimeout(()=>qs(!1),5e3)},[]);ze(()=>()=>clearTimeout(Ur.current),[]),ze(()=>{P&&!Me&&_r()},[P,Me,_r]);let Ge=Gs==="pointerLock",[Ws,cb]=U(null),Ys=ne(null),pb=Ws?.objectKey===L&&Ws?.textureKey==="texture",[ub,pn]=U(null),[bb,Vr]=U(null),Hn=nd(i,a),Eo=ed(Hn.tier);fi.current=Eo;let Js=td.models[Eo],gb=Ue(()=>({isInsideEditor:!0,activeTab:ht,activeSubTab:nn,tier:Eo,setActiveTab:on,setActiveSubTab:Tr,measurementPanelTarget:Ns,setMeasurementPanelTarget:As,measurementsPanelOpen:Os,setMeasurementsPanelOpen:Es,openMeasurementsPanel:zs,xrToolsTarget:js,annotating:Tt==="annotations"}),[ht,nn,Eo,Ns,Os,zs,js,Tt]),Je=ne(null),un=ne(0),vt=ne(0),Xs=ne(c?`${c.id}:${c.revision}`:null),Zs=ne(null),ov=ne(!1),Ni=ne(!1),Ai=ne(c?kn(c):null),Kr=ne(!1),Oi=ne(new Set),Ei=ne(new Map),ji=ne(void 0),bo=ne(0),mb=Xl(Au,bo.current===100),Le=ne(null),tt=ne(c?{requestId:0,modelName:B.name??"model",modelUrl:B.url,storedBindings:B.objectBindings,streaming:!!B.tilesetUrl}:null),qe=ne(B?{model:{kind:"url",url:B.url,name:B.name??"model"}}:null),Ii=ne(new Set),Zt=ne(new Map);Wp(ie.snapshot,H,{modelUrl:P,modelSourceRef:qe,uploadedFilesRef:Zt});let $n=ne(null),fb=ne(!1),Qt=ne(null),yt=ne(new Map),[Gr,Qs]=U(0),go=Ue(()=>new Map(_.map(r=>{let l=r===P?qe.current?.model:H.find(b=>b.url===r)?.sessionModel;return[r,l?Ut(l):`url:${r}`]})),[_,P,H]),Un=r=>rt.placements[go.get(r)??`url:${r}`]??{},me=Ue(()=>_.map((r,l)=>({id:go.get(r)??`url:${r}`,url:r,name:Un(r).label??(r===P?w:H.find(b=>b.url===r)?.name)??`Asset ${l+1}`,placement:Un(r),ready:yt.current.has(r)})).filter(r=>!r.placement.deleted),[_,P,w,H,rt,go,Gr]),el=St(Eo,"models",me.length),eo=Ue(()=>{let r=Hp(me.map(l=>l.name));return new Map(me.map((l,b)=>[l.url,r[b]]))},[me]),[qr,hb]=U(!1),[tl,ol]=U(null),[xb,nl]=U(null),vb=Z(()=>{let r=P?yt.current.get(P):void 0;!r||!P||ol({url:P,report:Gl(r,{source:{...Kl(r),name:w},scope:j?.tilesetUrl?"resident-tiles":"asset"})})},[P,w,j?.tilesetUrl]);ze(()=>{nl(null)},[P,qr]);let{materialVariantGroups:il,objectsWithoutUvs:rl,hierarchy:yb}=ru({modelUrl:P,scenesRef:yt,sceneRevision:Gr,streaming:!!j?.tilesetUrl});ze(()=>{let r=new Set(me.map(l=>l.url));for(let l of yt.current.keys())r.has(l)||yt.current.delete(l)},[me]),iu({enabled:!j?.tilesetUrl,modelUrl:P,bindings:q,mergeSources:Ee,parkedModels:H,scenesRef:yt,sceneRevision:Gr,setBindings:ie.setValueUntracked,setParkedModels:de});let jo=ne(null),[wb,Sb]=U(null),[al,kb]=U({}),Cb=Ue(()=>{if(!Oe||_e.length===0||!jo.current)return null;let l=_e.filter(b=>q[b]&&!q[b].removed).map(b=>al[b]).filter(b=>!!b);return l.length>0?l:null},[Oe,_e,al,q]),{cameraState:Pe,resetView:sl,focusObject:_n,fitScene:ll,setCameraState:zi,handleCameraChange:dl,handleViewerReady:Mb}=Rl(),{markThumbnailOutdated:Pb,noteThumbnailActivity:cl}=Xp({onCapture:M,hasThumbnail:y,viewerRef:jo,isModelLoading:()=>!P||!!tt.current}),Bb=Z((...r)=>{cl(),dl(...r)},[dl,cl]),pl=Z(r=>{Ge||zi({position:r.position,target:r.target,fov:r.fov??Pe?.fov??null,zoom:r.zoom??Pe?.zoom??1,azimuthAngle:r.azimuthAngle,polarAngle:r.polarAngle},!0)},[Ge,zi,Pe]),Nt=vd(),Tb=Ue(()=>me.map(r=>r.url),[me]),At=rc(Tb),Li=sc({modelUrl:P,sceneConfig:ee,setSceneConfig:Rt,setSceneConfigUntracked:Ti,parkedModels:H,setParkedModels:de,animations:At,markSessionEdited:at}),ul=ht==="configure"&&!po&&Ci&&ee.product,Rb=Ue(()=>ul&&ee.product?{...ee,product:{...ee.product,selections:Ci}}:ee,[ul,ee,Ci]),Nb=Z(r=>Rt(l=>({...r,product:l.product})),[Rt]);ze(()=>{ht!=="configure"&&Rs(null)},[ht]),ze(()=>{if(!po)return;let r=l=>{l.key==="Escape"&&Br(!1)};return window.addEventListener("keydown",r),()=>window.removeEventListener("keydown",r)},[po]);let Se=L?q[L]??null:null,Wr=Se?.style?.material,bl=!rl.has(Se?.modelObjectId??L??""),Ab=Ue(()=>{if(!(me.length<2))return me.map(r=>({url:r.url,label:eo.get(r.url)??r.name,bindings:r.url===P?q:H.find(l=>l.url===r.url)?.bindings??{},isActive:r.url===P}))},[me,eo,P,q,H]),Vn=Ue(()=>{let r=[];return me.forEach((l,b)=>{let S=l.url,k=S===P,E=k?void 0:H.find(K=>K.url===S),D=eo.get(S)||l.name||`Asset ${b+1}`;r.push({kind:"model",url:S,label:D,name:k?w:E?.name??"Untitled model",isActive:k}),(k?Ee:E?.mergedModelSources??[]).forEach(K=>{r.push({kind:"merge",url:K.url,label:"Merged nodes",name:Gt(K.namePrefix),ownerLabel:D})})}),c&&me.length<2?r.filter(l=>l.kind!=="model"):r},[c,me,P,w,H,Ee]),Yr=Ue(()=>Ee.map(r=>({url:r.url,namePrefix:r.namePrefix})),[Ee]),Ob=Ue(()=>(c?_.length<2:_.length<1)?void 0:_.map((l,b)=>{let S=rt.placements[go.get(l)??`url:${l}`]??{},k={transform:S,visible:S.visible!==!1&&!S.deleted,label:S.label};if(l===P)return{url:l,label:eo.get(l)??k.label??(w||`Model ${b+1}`),transform:k.transform,visible:k.visible,objectBindings:q,originalNodePoses:xt.current,mergeModels:Yr};let D=H.find(F=>F.url===l);return{url:l,label:eo.get(l)??k.label??(D?.name||`Model ${b+1}`),transform:k.transform,visible:k.visible,objectBindings:D?.bindings??{},originalNodePoses:D?.originalTransforms,sceneConfig:Xe(ee,D?.modelSettings),mergeModels:(D?.mergedModelSources??[]).map(F=>({url:F.url,namePrefix:F.namePrefix}))}}).filter(l=>!rt.placements[go.get(l.url)??`url:${l.url}`]?.deleted),[c,_,P,w,q,H,Yr,ee,rt,go,eo]);ze(()=>{let r=N.current;if(r)return r.style.setProperty("--bb-canvas-hint-top",Oo?"48px":"12px"),()=>{r.style.removeProperty("--bb-canvas-hint-top")}},[Oo]);let mo=Se?.cameraState,Eb=Pe?{position:Ia(Pe.position),target:Ia(Pe.target)}:null,jb=Z(r=>{Rt(l=>{let b=l.annotations.map(k=>k.id).join(","),S=r.map(k=>k.id).join(",");return b===S?l:r.length>l.annotations.length&&!St(fi.current,"annotations",l.annotations.length)?(W(`More annotations require the ${ua[Ho("annotations",l.annotations.length)]} plan or higher.`),X("error"),l):{...l,annotations:r}})},[]),Ib=Z(r=>{pn(r?{annotation:r}:null)},[]);ze(()=>{if(!Se){vi("{}"),yi("{}"),wi(null),Si(null);return}vi(ja(Se.metrics)),yi(ja(Se.metadata)),wi(null),Si(null)},[Se]),ze(()=>{let r=us(Wr);if(Ls.current!==L){Ls.current=L,Rr(r);return}Rr(l=>{let b=!1,S={...l};for(let k of hu)r[k]&&!l[k]&&(S[k]=!0,b=!0);return b?S:l})},[L,Wr]),ze(()=>()=>{Je.current?.cleanup(),Le.current&&clearTimeout(Le.current)},[]);let Di=Z((r,l)=>{let b=Yn(r);if(l){let S=new Map(Object.values(l).map(k=>[k.modelObjectId,k]));for(let k of r){let E=S.get(k);E&&(b[k]=E)}}return b},[]);ze(()=>{if(!c)return;let r=`${c.id}:${c.revision}`;if(Xs.current===r)return;Xs.current=r,J.current=Ca(c);let l=c.models.find(te=>te.url===P),b=l&&!c.composition.placements[Vo(l.url)]?.deleted?l:wa(c),S=er(c.sceneConfig,b),k=P!==b.url||he?.tilesetUrl!==b.tilesetUrl||he?.assetVersion!==b.assetVersion,E=kn(c);if(!k&&Oi.current.delete(E)){Ai.current=E;return}Oi.current.clear();let D=!tr(q,b.objectBindings),F=!tr(ee,S);Ne(b),I(b.name??"model");let K=b.objectBindings;if(D){let te=Zs.current;K=te?Di(te,b.objectBindings):b.objectBindings,ie.reset(K)}else K=q;F&&Be.reset(S),de(te=>c.models.filter(ke=>ke.url!==b.url).map(ke=>{let ct=te.find(Ot=>Ot.url===ke.url);if(!ct)return ka(ke);let we=JSON.stringify(ct.mergedModelSources.map(Ot=>Ot.url))===JSON.stringify((ke.mergeModels??[]).map(Ot=>Ot.url));return{...ct,name:ke.name??ct.name,bindings:ke.objectBindings,modelSettings:ke.modelSettings,mergedModelSources:we?ct.mergedModelSources:Sn(ke),bindingHistory:we?ct.bindingHistory:void 0}})),Q(c.models.map(te=>te.url));let le=(b.mergeModels??[]).map(te=>te.url);if(JSON.stringify(Ee.map(te=>te.url))!==JSON.stringify(le)&&(so(Sn(b)),ie.clearHistory()),tr(Ve.value,c.composition)||Ve.reset(Sa(c)),k){Nt.clearAnimations();let te=++vt.current;tt.current={requestId:te,modelName:b.name??"model",modelUrl:b.url,storedBindings:b.objectBindings,streaming:!!b.tilesetUrl},qe.current={model:{kind:"url",url:b.url,name:b.name??"model"}},Qt.current=null,Ce(null),qt(!0),$(b.url)}Ai.current=kn({models:c.models.map(te=>te===b?{...te,objectBindings:K}:te),composition:c.composition,sceneConfig:c.sceneConfig})},[he,q,Di,Ve,Ee,c,P,ee,ie,Be,so,Nt.clearAnimations]);let Jr=ne(x);Jr.current=x;let gl=ne(C);gl.current=C,ze(()=>{if(!c||!Jr.current||!P||tt.current)return;let r=()=>Ud({project:c,modelUrl:P,modelName:w,bindings:q,sceneConfig:ee,mergedModelSources:Ee,parkedModels:H,modelOrder:_,composition:rt,sources:J.current});Ni.current&&(Ni.current=!1,Ai.current=kn({...r(),composition:c.composition,sceneConfig:c.sceneConfig}));let l=window.setTimeout(()=>{if(Kr.current)return;let b=r(),S=kn(b);if(S===Ai.current||Oi.current.has(S))return;let k=gl.current,E=k?_o(b.models).size+_o(b.sceneConfig).size:0;if(k&&E>0){Kr.current=!0;let D=_o(b.sceneConfig,_o(b.models));Promise.all([...D].map(async F=>{if(!Ei.current.has(F))try{Ei.current.set(F,await k(await Vd(F),F))}catch(K){W(K instanceof Error?K.message:"Could not save an image."),X("error"),Ei.current.set(F,"")}})).then(()=>{Kr.current=!1;let F=K=>Qi(K,Ei.current);ie.setValueUntracked(F),Be.setValueUntracked(F),de(K=>K.map(le=>({...le,bindings:F(le.bindings),modelSettings:F(le.modelSettings)})))});return}Oi.current.add(S),Jr.current?.(b,"local"),Pb()},h);return()=>window.clearTimeout(l)},[q,rt,Ee,w,_,P,H,c,h,ee]);let Io=Ln==="assets"?Ve:Ln==="scene"?Be:ie;ze(()=>{let r=l=>{l.key.toLowerCase()!=="z"||!(l.metaKey||l.ctrlKey)||Pu(l.target)||(l.preventDefault(),l.shiftKey?Io.redo():Io.undo())};return window.addEventListener("keydown",r),()=>window.removeEventListener("keydown",r)},[Io]);let Fi=!c&&f,{handleTextureUpload:zb}=Yp({composition:rt,autosaveEnabled:Fi,hasEdits:ib,modelUrl:P,bindings:q,sceneConfig:ee,parkedModels:H,mergedModelSources:Ee,modelOrder:_,onTextureUpload:C,modelSourceRef:qe,pendingLoadRef:tt,storedModelKeysRef:Ii,uploadedFilesRef:Zt,pendingAutosaveRef:$n,autosaveFailureShownRef:fb,setStatusMessage:W,setStatusTone:X});ze(()=>{Me||yr==="default"||ws({id:Date.now(),text:vr,tone:yr})},[vr,yr,Me]);let Ht=Ue(()=>Object.keys(q),[q]),Lb=Ue(()=>!L||!Se?null:Se.id.trim()?Object.entries(q).some(([b,S])=>b!==L&&S.id===Se.id)?"Another binding already uses this ID.":null:"ID is required.",[q,L,Se]),wt=(r,l)=>{To(b=>{let S=vs.current,k=S.mode&&S.keys.includes(r)?S.keys.filter(D=>b[D]):[r];if(k.length<=1)return{...b,[r]:l(b[r],r)};let E={...b};for(let D of k){let F=b[D];E[D]={...l(F,D),id:F.id,modelObjectId:F.modelObjectId}}return E})},Xr=(r,l)=>{wt(r,b=>{let S=ps(l(b.style?.material));return bs(b,S)})},Db=(r,l,b)=>{Xr(r,S=>({...S,[l]:b?{path:b}:void 0}))},Fb=(r,l)=>{Rr(b=>({...b,[r]:l})),!l&&L&&wt(L,b=>{let S=ps(vu(b.style?.material,r));return bs(b,S)})},Zr=Z((r,l,b)=>{let{bindings:S,originalTransforms:k,nodeNames:E}=pi(r,b);xt.current=k,ie.reset(Xo(r,b??{},Ee,S)),Ce(E[0]??null),b||Ti(F=>({...F,annotations:[]})),W(`Generated ${E.length} bindings from ${l}.`),X("success"),Le.current&&clearTimeout(Le.current);let D=setTimeout(()=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{Le.current===D&&(bo.current=100,Ro(100),Le.current=setTimeout(()=>{Le.current=null,qt(!1),Ro(null)},400))})})},0);Le.current=D},[ie,Ti,Ee]),Qr=(r,l,b,S)=>{$n.current?.();let k=++vt.current;zr(),Ve.reset(Do),an([]),c||Be.reset(r!==P?Xe(ee):ee),r!==P&&Nt.clearAnimations(),H.forEach(F=>F.resolved?.cleanup()),de([]),Q([r]),so([]),qt(!0),Ro(null),bo.current=0,Le.current&&(clearTimeout(Le.current),Le.current=null),ji.current=b;let E=b?b/1048576:0;W(E>=100?`Reading the file. At ${Math.round(E)} MB, this can take a while.`:"Reading the file and generating bindings."),X("default"),I(l),Ne(S??{url:r,name:l}),pn(null);let D=Qt.current;if(r===P&&D?.url===r){tt.current=null,Zr(D.scene,l);return}tt.current={requestId:k,modelName:l,modelUrl:r,streaming:!!S?.tilesetUrl},$(r),ie.reset({}),Ce(null)},Hb=Z(r=>{P&&yt.current.get(P)!==r&&(yt.current.set(P,r),Qs(b=>b+1));let l=tt.current;if(!(l&&l.requestId!==vt.current)&&(P&&(Qt.current={url:P,scene:r}),lo(null),In(null),!!l)){if(tt.current=null,l.streaming){W(`Streaming ${l.modelName}.`),X("success"),qt(!1);return}l.storedBindings&&(Ni.current=!0),Zr(r,l.modelName,l.storedBindings),l.restoring&&W(`Restored your last session with ${l.modelName}.`)}},[Zr,P]),$b=Z(r=>{if(!j?.tilesetUrl)return;let l=r.map(k=>k.name);if(l.length===0)return;Zs.current=l,Ni.current=!0;let b=c?.models.find(k=>k.url===P)?.objectBindings,S=Di(l,b);ie.reset(S),Ce(k=>k??l[0]??null),W(`Streaming ${l.length} bindable objects.`),X("success"),qt(!1)},[Di,ie,P,c,j]),Ub=Z(r=>{let l=tt.current;if(!(l&&l.requestId!==vt.current)){if(tt.current=null,console.error(r),l?.restoring)qe.current=null,$(null),W(ms(l.modelName));else if(l)W(ql(r)?`${l.modelName} is a point cloud: it has points but no faces. Turn it into a mesh first, for example with MeshLab or Blender.`:`Could not read ${l.modelName}. Make sure the file is a valid GLB, GLTF, OBJ, FBX, USDZ, STL, or PLY asset.`);else{let{detail:b}=qi(r,P??"",Je.current?.format);W(`Could not read ${w||"the model"}. ${b}`)}X("error"),Le.current&&(clearTimeout(Le.current),Le.current=null),bo.current=0,qt(!1),Ro(null)}},[P,w]),_b=Z(r=>{let l=null;if(r.lengthComputable&&r.total>0)l=r.loaded/r.total*100;else{let S=ji.current;S&&S>0&&(l=r.loaded/S*100)}if(l===null)return;let b=Math.min(99,Math.floor(l));b>bo.current&&(bo.current=b),Ro(S=>l>=99.5?100:Math.max(S??0,b)),l>=99.5&&W(S=>S.startsWith("Finalizing")?S:"Finalizing: parsing geometry and textures.")},[]),Vb=Z(r=>{Nt.handleAnimationsReady(r),P&&At.handleModelAnimationsReady(P,r)},[Nt,P,At.handleModelAnimationsReady]),nv=async()=>{Je.current?.cleanup(),Je.current=null,qe.current={model:{kind:"url",url:ku,name:"room.glb"}},await Qr(ku,"room.glb")},ml=async r=>{if(!f)return;if(r.name.toLowerCase().endsWith(".ri.zip")){await kl(r);return}if(g){try{qt(!0),W(`Uploading ${r.name}...`),X("default");let S=await g(r);J.current.set(S.url,S),qe.current={model:{kind:"url",url:S.url,name:S.name??r.name}},await Qr(S.url,S.name??r.name,r.size,S)}catch(S){qt(!1),W(S instanceof Error?S.message:`Could not upload ${r.name}.`),X("error")}return}let l;try{l=await ho(r)}catch(S){W(S instanceof Error?S.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, .stl, .ply, or .zip asset."),X("error");return}Je.current?.cleanup(),Je.current=l;let b=gs();Zt.current.set(b,r),qe.current={model:{kind:"file",key:b,name:l.name},file:r},await Qr(l.url,l.name,r.size,{url:l.url,name:l.name})},Kb=async r=>{let l=r.target.files?.[0];l&&(await ml(l),r.target.value="")},Hi=()=>{$n.current=null,at(),Je.current?.cleanup(),Je.current=null,Qt.current=null,tt.current=null,qe.current=null,Nt.clearAnimations(),xt.current={},un.current=0,zn(!1),Le.current&&(clearTimeout(Le.current),Le.current=null),bo.current=0,Ro(null),ji.current=void 0,$(null),I(""),H.forEach(r=>r.resolved?.cleanup()),de([]),Q([]),Ve.reset(Do),an([]),so([]),Ne(null),Ce(null),pn(null),ie.reset({}),vi("{}"),yi("{}"),wi(null),Si(null),Vr(null),Bi("select"),Ti(r=>Xe(r)),W(""),X("default")},fl=r=>c?{...r,bindingHistory:void 0}:r,Gb=()=>{Vn.length>1?rn(!0):Hi()},qb=()=>{rn(!1)},Wb=r=>{if(rn(!1),_.length<=1){Hi();return}if(!_.includes(r))return;if(at(),r!==P){let E=H.find(D=>D.url===r);E?.resolved?.cleanup(),de(D=>D.filter(F=>F.url!==r)),Q(D=>D.filter(F=>F!==r)),W(`Removed ${E?.name??"the model"}.`),X("success");return}let l=_.filter(E=>E!==r),b=l[0],S=H.findIndex(E=>E.url===b),k=H[S];if(!k){Hi();return}Je.current?.cleanup(),de(E=>E.filter((D,F)=>F!==S)),Q(l),Je.current=k.resolved??null,qe.current={model:k.sessionModel??{kind:"url",url:k.url,name:k.name}},Qt.current=null,tt.current=null,xt.current=k.originalTransforms,Nt.clearAnimations(),Ir(k),$(k.url),I(k.name),Ne(J.current.get(k.url)??{url:k.url,name:k.name}),ie.restoreModel(k),Ce(Object.keys(k.bindings)[0]??null),pn(null),W(`Removed the model \u2014 now viewing ${k.name}.`),X("success")},Yb=r=>{rn(!1);let l=Ee.find(k=>k.url===r);if(l){at(),ie.removeMerge(r),c&&ie.clearHistory(),W(`Removed ${Gt(l.namePrefix)}.`),X("success");return}let b=H.find(k=>k.mergedModelSources.some(E=>E.url===r));if(!b)return;let S=b.mergedModelSources.find(k=>k.url===r);S&&(at(),de(k=>k.map(E=>E.url!==b.url?E:fl(ts(E,D=>es(D,r))))),W(`Removed ${Gt(S.namePrefix)}.`),X("success"))},hl=()=>{v.current?.click()},ea=()=>{Er(!0)},Jb=r=>{let l=r.target.files?.[0];r.target.value="";let b=Mi.current;Mi.current=null,!(!l||!f||!b)&&(b.mode==="separate"?Qb(l):eg(l,b.targetUrl))},Xb=Z(()=>{Mi.current=null,Er(!1)},[]),Zb=Z(r=>{Mi.current=r,Er(!1),m.current?.click()},[]),ta=Z(async r=>{if(c&&g){W(`Uploading ${r.name}...`),X("default");let S=await g(r);J.current.set(S.url,S);let k=S.name??r.name;return{resolved:{url:S.url,name:k,format:"glb",cleanup:()=>{}},sessionModel:{kind:"url",url:S.url,name:k}}}let l=await ho(r),b=gs();return Zt.current.set(b,r),{resolved:l,sessionModel:{kind:"file",key:b,name:l.name}}},[c,g]),Qb=Z(async r=>{if(!St(fi.current,"models",Pi.current.modelOrder.length)){W("Your plan has no room for another model in this project. Upgrade to add more."),X("error");return}let l,b;try{({resolved:l,sessionModel:b}=await ta(r))}catch(S){W(S instanceof Error?S.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, or .zip asset."),X("error");return}de(S=>[...S,{url:l.url,name:l.name,bindings:{},originalTransforms:{},resolved:l,sessionModel:b,mergedModelSources:[]}]),Q(S=>[...S,l.url]),at(),W(`Added ${l.name} as a separate model.`),X("success")},[at,ta]),eg=Z(async(r,l)=>{let b,S;try{({resolved:b,sessionModel:S}=await ta(r))}catch(K){W(K instanceof Error?K.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, or .zip asset."),X("error");return}let k=Pi.current,E=k.parkedModels.find(K=>K.url===l);if(!k.modelOrder.includes(l)||l!==k.modelUrl&&!E){b.cleanup(),W("The destination model was removed. Choose a model and add the file again."),X("error");return}let D={url:b.url,resolved:b,sessionModel:S,nodeNames:[],loadState:"loading"};l===k.modelUrl?(ie.addMerge(K=>({...D,namePrefix:Za(b.name,K.mergeSources,K.bindings)})),c&&ie.clearHistory()):de(K=>{let le=K.findIndex(ke=>ke.url===l);if(le===-1)return K;let te=[...K];return te[le]=fl(ts(te[le],ke=>({...ke,mergeSources:[...ke.mergeSources,{...D,namePrefix:Za(b.name,ke.mergeSources,ke.bindings)}]}))),te});let F=l===k.modelUrl?k.modelName:E?.name;at(),W(`Merging ${b.name} into ${F||"the model"}...`),X("default")},[ie.addMerge,at]),tg=Z((r,l)=>{let b=Ee.find(K=>K.url===r);if(b){let{bindings:K,originalTransforms:le,nodeNames:te}=Qa(l,q);ie.hydrateMerge(r,{nodeNames:te,loadState:"loaded"},K),xt.current={...xt.current,...le},W(`Merged ${te.length} node${te.length===1?"":"s"} from ${b.namePrefix||"the added model"} into ${w||"the model"}.`),X("success");return}let S=H.find(K=>K.mergedModelSources.some(le=>le.url===r));if(!S)return;let k=S.mergedModelSources.find(K=>K.url===r);if(!k)return;let{bindings:E,originalTransforms:D,nodeNames:F}=Qa(l,S.bindings);de(K=>K.map(le=>le.url!==S.url?le:{...os(le,r,{nodeNames:F,loadState:"loaded"},E),originalTransforms:{...le.originalTransforms,...D}})),W(`Merged ${F.length} node${F.length===1?"":"s"} from ${k.namePrefix||"the added model"} into ${S.name||"the model"}.`),X("success")},[ie.hydrateMerge,w,Ee,q,H]),og=Z((r,l)=>{let b=Ee.find(k=>k.url===r)??H.flatMap(k=>k.mergedModelSources).find(k=>k.url===r);if(!b)return;ie.hydrateMerge(r,{loadState:"failed"}),de(k=>k.map(E=>E.mergedModelSources.some(D=>D.url===r)?os(E,r,{loadState:"failed"}):E));let{detail:S}=qi(l,r,b.resolved.format);W(`Could not merge ${b.resolved.name}. ${S} Remove the failed file using the Remove model menu.`),X("error")},[Ee,H,ie.hydrateMerge]),ng=Z((r,l)=>{let b=H.find(k=>k.url===r);if(!b)return;let{detail:S}=qi(l,r,b.resolved?.format);W(`Could not read ${b.name}. ${S} Remove the failed file using the Remove model menu.`),X("error")},[H]),ig=Z((r,l)=>{yt.current.get(r)!==l&&(yt.current.set(r,l),Qs(b=>b+1)),de(b=>{let S=b.findIndex(F=>F.url===r);if(S===-1)return b;let{bindings:k,originalTransforms:E}=pi(l,b[S].bindings),D=[...b];return D[S]={...Kp(D[S],k),bindings:Xo(l,b[S].bindings,b[S].mergedModelSources,k),originalTransforms:{...E,...b[S].originalTransforms}},D})},[]),zo=Z(r=>{if(r===P)return;let l=H.findIndex(k=>k.url===r);if(l===-1)return;let b=H[l];$n.current?.(),at();let S=P?{url:P,name:w,bindings:q,originalTransforms:xt.current,resolved:Je.current??void 0,sessionModel:qe.current?.model,mergedModelSources:Ee,modelSettings:xo(ee),bindingHistory:ie.snapshot,sceneHistory:Be.snapshot}:null;de(k=>{let E=k.filter((D,F)=>F!==l);return S?[...E,S]:E}),Je.current=b.resolved??null,qe.current={model:b.sessionModel??{kind:"url",url:b.url,name:b.name}},Qt.current=null,tt.current=null,Nt.clearAnimations(),Ir(b),xt.current=b.originalTransforms,$(b.url),I(b.name),Ne(J.current.get(b.url)??{url:b.url,name:b.name}),ie.restoreModel(b),Ce(Object.keys(b.bindings)[0]??null),pn(null)},[P,w,q,H,ie,Ee,ee,Be,Ir,Nt.clearAnimations,at]),rg=()=>{A.current?.click()};ze(()=>{P&&me.length&&!me.some(r=>r.url===P)&&zo(me[0].url)},[P,me,zo]);let{handleExportBindings:xl,handleExportSceneConfig:vl,handleImportBindingsChange:ag,openSceneConfigImportPicker:sg,handleImportSceneConfigChange:lg}=fu({bindings:q,setBindings:To,sceneConfig:ee,setSceneConfig:Rt,nodeKeys:Ht,sceneConfigInputRef:G,setIsExporting:Ou,setStatusMessage:W,setStatusTone:X}),dg=r=>{r.preventDefault(),r.stopPropagation(),!(Me||P)&&(un.current+=1,zn(!0))},cg=r=>{r.preventDefault(),r.stopPropagation(),!(Me||P)&&(r.dataTransfer.dropEffect="copy",zn(!0))},pg=r=>{r.preventDefault(),r.stopPropagation(),!(Me||P)&&(un.current=Math.max(0,un.current-1),un.current===0&&zn(!1))},ug=async r=>{if(r.preventDefault(),r.stopPropagation(),un.current=0,zn(!1),Me||P)return;let l=r.dataTransfer.files?.[0];l&&await ml(l)},yl=(r,l,b)=>{if(!L)return;let S;try{S=JSON.parse(l)}catch{b("Invalid JSON");return}if(S===null||typeof S!="object"||Array.isArray(S)){b("Expected a JSON object");return}if(r==="metrics"&&Object.values(S).some(E=>typeof E!="number"||!Number.isFinite(E))){b("Metrics values must be numbers");return}wt(L,k=>({...k,[r]:S})),b(null)},wl=Z((r,l)=>{Fi&&wn(r,l).catch(b=>console.warn("[BindingBuilder] Could not store decal image for autosave:",b))},[Fi]),bg=Ue(()=>{let r=Qt.current?.scene,b=(r&&L?Gn(r,L):null)?.geometry;if(!b)return .2;b.boundingBox||b.computeBoundingBox();let S=b.boundingBox?.getSize(new Ox),k=S?Math.max(S.x,S.y,S.z):0;return k>0&&Number.isFinite(k)?k/3:.2},[L,P,Me]),gg=Ue(()=>{if(!xi?.moving)return null;let{nodeKey:r,decal:l}=xi,b=q[r],S=b?.decals?.find(k=>k.id===l.id);return S?{objectId:b.modelObjectId??r,decal:S,onCancel:()=>lo(null),onCommit:k=>{To(E=>{let D=E[r];return D?{...E,[r]:{...D,decals:D.decals?.map(F=>F.id===S.id?{...F,...k}:F)}}:E}),lo(null)}}:null},[q,xi,To]),mg=Z((r,l)=>{if(!L)return;let b=q[L],S=b?.decals?.find(F=>F.id===r);if(!S)return;let k=jo.current,E=k?.raw.nodes[b.modelObjectId??L],D=pd(E,k?.raw.controls.camera,S,l);if(!D){W("No visible surface in that direction. Try another arrow or rotate the view."),X("error");return}lo(null),wt(L,F=>({...F,decals:F.decals?.map(K=>K.id===r?{...K,...D}:K)}))},[q,L,wt]),fg=Z(r=>{if(!r||r.moving){lo(r);return}let l=jo.current,b=q[r.nodeKey],S=l?.raw.nodes[b?.modelObjectId??r.nodeKey],k=cd(S,l?.raw.controls.camera);if(!k){W("Could not find a surface on this object for the decal."),X("error");return}let E={...r.decal,...k};To(D=>{let F=D[r.nodeKey];if(!F)return D;let K=(F.decals??[]).filter(le=>le.id!==E.id);return{...D,[r.nodeKey]:{...F,decals:[...K,E]}}}),lo({...r,moving:!0})},[q,To]),hg=Z((r,l)=>{let b=Object.entries(q).find(([F,K])=>K===r||F===r.modelObjectId||K.modelObjectId===r.modelObjectId)?.[0],S=b?q[b]?.decals?.find(F=>F.id===l):void 0;if(!b||!S)return;on("object"),Ts(F=>({...F,decals:!0})),Ce(b);let{position:k,normal:E,...D}=S;setTimeout(()=>lo({nodeKey:b,decal:D,moving:!0}),0)},[q]),xg=Z(r=>{let l=[...new Set(r)].filter(b=>q[b]&&!q[b].removed);fs(l)},[q,fs]),vg=Z(r=>{let l=mi.current;if(mi.current={shiftKey:!1,ctrlKey:!1,metaKey:!1},Ge){$r("orbit");return}if(!r){En(null);return}let b=Object.entries(q).find(([S,k])=>k===r||S===r.modelObjectId||k.modelObjectId===r.modelObjectId)?.[0]??null;En(b,l)},[Ge,q,En]),oa=Z(async r=>{if(Ge){$r("orbit");return}En(r),!tn&&(Vr(null),await _n(r))},[Ge,_n,tn,En]),yg=Z(r=>{Vr(r?q[r]??null:null)},[q]),wg=Z(()=>{if(Ge){W("Camera positions aren't available while Pointer Lock is the active camera controller."),X("error");return}if(!L||!Pe)return;let r={position:Pe.position,target:Pe.target,...Pe.fov!=null?{fov:Pe.fov}:{},zoom:Pe.zoom};wt(L,l=>({...l,cameraState:r}))},[Ge,L,Pe]),Sg=Z(()=>{if(Ge){W("Camera positions aren't available while Pointer Lock is the active camera controller."),X("error");return}!mo?.position||!mo?.target||zi({position:mo.position,target:mo.target,fov:mo.fov??Pe?.fov??null,zoom:mo.zoom??Pe?.zoom??1},!0)},[Ge,mo,zi,Pe]),kg=Z(()=>{Ge||L&&wt(L,r=>({...r,cameraState:void 0}))},[Ge,L]),Sl=Z(async()=>{if(Ge){W("Reset view isn't available while Pointer Lock is the active camera controller."),X("error");return}await sl()},[Ge,sl]),Kn=Z(async()=>{if(Ge){W("Fit scene isn't available while Pointer Lock is the active camera controller."),X("error");return}await ll()},[Ge,ll]),Cg=Z(()=>{W("Texture position saved."),X("success"),Ys.current?.()},[]),Mg=Z(r=>{Hs(r),Fs(!0)},[]),$i=Z(()=>{Fs(!1),Hs(null)},[]),Pg=Z(()=>{if(Dn==="bindings"){if(!Ht.length){$i();return}let r=Yn(Ht,rl);ie.reset(r,{asEdit:!0}),Ce(Ht[0]??null),W("Object bindings reset to default values."),X("success")}else Dn==="assets"?(Ve.setValueAsStep(r=>({...r,gridSize:Do.gridSize,placements:Object.fromEntries(Object.entries(r.placements).map(([l,b])=>{let{position:S,rotation:k,scale:E,...D}=b;return[l,D]}))})),W("Asset placements reset to default values."),X("success")):Dn==="scene"&&(Be.reset(fo,{asEdit:!0}),W("Scene config reset to default values."),X("success"));$i()},[Dn,Ht,ie,Be,Ve,$i]),Bg=Z(r=>{r.length>0&&jr(r)},[]),Tg=Z(()=>{jr(null)},[]),Rg=Z(()=>{let r=uo;if(!r||r.length===0)return;let l=new Set(r);ie.setValueAsStep(b=>{let S={...b};for(let k of r)b[k]&&(S[k]={...b[k],removed:!0});return S}),Ce(b=>b&&l.has(b)?null:b),xr(b=>b.filter(S=>!l.has(S))),In(b=>b&&l.has(b)?null:b),W(r.length===1?`Deleted ${q[r[0]]?.label||r[0]}.`:`Deleted ${r.length} objects.`),X("success"),jr(null)},[uo,q,ie.setValueAsStep]),Ng=Z(()=>{Or(null)},[]),Ag=async()=>{let r;try{r=await Hd()}catch(l){console.warn("[BindingBuilder] Could not read the saved session:",l),W("Couldn't read the saved session from this browser."),X("error");return}if(!r){W("No saved session in this browser. Sessions are saved when you edit a model or add another one."),X("error");return}Or(r)},na=async(r,l)=>(await Promise.all(r.map(async({entry:S,file:k})=>{if(S.model.kind==="url"&&c)return Sn({url:"",objectBindings:{},mergeModels:[{url:S.model.url,namePrefix:S.namePrefix}]})[0];if(S.model.kind==="url")return console.warn(`[BindingBuilder] Could not restore merged model "${S.model.name}" \u2014 merged models must come from an uploaded file.`),null;if(!k)return console.warn(`[BindingBuilder] Could not restore merged model "${S.model.name}" \u2014 its file is no longer in this browser's storage.`),null;try{let E=await ho(k);return l.set(S.model.key,k),{url:E.url,namePrefix:S.namePrefix,resolved:E,sessionModel:S.model,nodeNames:[],loadState:"loading"}}catch(E){return console.warn(`[BindingBuilder] Could not restore merged model "${S.model.name}":`,E),null}}))).filter(S=>S!==null),Og=async(r,l,b)=>{let S=await Promise.all(r.map(async({entry:E,file:D,mergeFiles:F})=>{if(await gi(E.modelSettings?.product),E.model.kind==="url")return{url:E.model.url,name:E.model.name,bindings:await Qo(E.bindings),originalTransforms:E.originalTransforms,modelSettings:E.modelSettings,sessionModel:E.model,mergedModelSources:await na(F,b)};if(!D)return console.warn(`[BindingBuilder] Could not restore parked model "${E.model.name}" \u2014 its file is no longer in this browser's storage.`),null;try{let K=await ho(D);return b.set(E.model.key,D),{url:K.url,name:E.model.name,bindings:await Qo(E.bindings),originalTransforms:E.originalTransforms,modelSettings:E.modelSettings,resolved:K,sessionModel:E.model,mergedModelSources:await na(F,b)}}catch(K){return console.warn(`[BindingBuilder] Could not restore parked model "${E.model.name}":`,K),null}})),k=await na(l,b);return{parkedModels:S.filter(E=>E!==null),mergedModelSources:k}},ia=(r,l)=>{Ve.setValue(b=>({...b,placements:{...b.placements,[r]:{...b.placements[r],...l}}}))},Eg=async r=>{if(sn||!f||!el)return;let l=r===P?{url:r,name:w,bindings:q,originalTransforms:xt.current,resolved:Je.current??void 0,sessionModel:qe.current?.model,mergedModelSources:Ee,modelSettings:xo(ee)}:H.find(k=>k.url===r);if(!l?.sessionModel)return;if(c){let k=`${r.split("#")[0]}#copy-${crypto.randomUUID()}`,E=Vo(k),D=J.current.get(r);J.current.set(k,{...D,url:k});let F=`${l.name} copy`,K=structuredClone(l.modelSettings);K?.measurements&&(K.measurements.items=K.measurements.items.map(we=>({...we,modelId:E}))),de(we=>[...we,{...l,url:k,name:F,resolved:void 0,sessionModel:{kind:"url",url:k,name:F},bindings:structuredClone(l.bindings),originalTransforms:structuredClone(l.originalTransforms),modelSettings:K,mergedModelSources:l.mergedModelSources.map(Ot=>({...Ot,loadState:"loading"})),bindingHistory:void 0,sceneHistory:void 0}]),Q(we=>[...we,k]),an(we=>[...we,E]);let le=Un(r),[te,ke,ct]=le.position??[0,0,0];Ve.setValueAsStep(we=>({...we,placements:{...we.placements,[E]:{...le,deleted:!1,label:`${le.label??l.name} copy`,position:[te+rt.gridSize,ke,ct]}}})),at(),W(`Duplicated ${l.name}.`),X("success");return}ln(!0);let b=vt.current,S=[];try{let E=(l.sessionModel.kind==="file"?Zt.current.get(l.sessionModel.key):void 0)??new File([await(await fetch(l.url)).blob()],l.name),D=await ho(E);S.push(D);let F=gs(),K=`file:${F}`,le=[];for(let fe of l.mergedModelSources){if(fe.sessionModel.kind!=="file")throw new Error("Cannot duplicate a merged source without its original file.");let ot=Zt.current.get(fe.sessionModel.key);if(!ot)throw new Error("An added source file is unavailable.");let Et=await ho(ot);S.push(Et),le.push({...fe,resolved:Et,url:Et.url,loadState:"loading"})}if(b!==vt.current||!Pi.current.modelOrder.includes(r)){S.forEach(fe=>fe.cleanup());return}Zt.current.set(F,E);let te=structuredClone(l.modelSettings);te?.measurements&&(te.measurements.items=te.measurements.items.map(fe=>({...fe,modelId:K}))),de(fe=>[...fe,{...l,url:D.url,name:`${l.name} copy`,resolved:D,sessionModel:{kind:"file",key:F,name:E.name},bindings:structuredClone(l.bindings),originalTransforms:structuredClone(l.originalTransforms),modelSettings:te,mergedModelSources:le,bindingHistory:void 0,sceneHistory:void 0}]),Q(fe=>[...fe,D.url]),an(fe=>[...fe,K]);let ke=Un(r),[ct,we,Ot]=ke.position??[0,0,0];Ve.setValueAsStep(fe=>({...fe,placements:{...fe.placements,[K]:{...ke,deleted:!1,label:`${ke.label??l.name} copy`,position:[ct+rt.gridSize,we,Ot]}}})),at(),W(`Duplicated ${l.name}.`),X("success")}catch(k){S.forEach(E=>E.cleanup()),W(k instanceof Error?k.message:"Could not duplicate asset."),X("error")}finally{ln(!1)}},jg=r=>{if(me.length<2||!f)return;let l=me.find(b=>b.url===r);l&&(r===P&&zo(me.find(b=>b.url!==r).url),Ve.setValueAsStep(b=>({...b,placements:{...b.placements,[l.id]:{...b.placements[l.id],deleted:!0}}})))},kl=async r=>{if(!(sn||!f)){if(!nt(fi.current,"sceneBundle")){W(`Importing a complete scene requires the ${ua.starter} plan or higher.`),X("error");return}ln(!0);try{let l=await Yd(r);if(c){if(!g)throw new Error("This project can't accept new models.");let b=S=>l.session.composition?.placements[Ut(S)]?.deleted;if(1+l.parkedFiles.filter(S=>!b(S.entry.model)).length>Js)throw new Error(`Your plan allows ${Js} models per project. Upgrade to import this scene.`);W(`Uploading the models in ${r.name}...`),X("default"),l=await Kd(l,async S=>{let k=await g(S);return J.current.set(k.url,k),k})}await Cl(l),at()}catch(l){W(l instanceof Error?l.message:"Could not load scene bundle."),X("error")}finally{ln(!1)}}},Ig=async()=>{let r=qe.current;if(!(!r||!P||sn)){ln(!0);try{let l=k=>({model:k.sessionModel,namePrefix:k.namePrefix}),b={model:r.model,bindings:q,sceneConfig:ee,composition:rt,mergeModels:Ee.map(l),parkedModels:H.map(k=>({model:k.sessionModel??{kind:"url",url:k.url,name:k.name},bindings:k.bindings,originalTransforms:k.originalTransforms,modelSettings:k.modelSettings,mergeModels:k.mergedModelSources.map(l)})),modelOrder:_.map(k=>go.get(k)).filter(Boolean)},S=await Wd(b,new Map(Zt.current));fn(S,"scene.ri.zip"),W("Saved complete scene bundle."),X("success")}catch(l){W(l instanceof Error?l.message:"Could not save scene."),X("error")}finally{ln(!1)}}},Cl=async r=>{let l=r??Ao;if(Or(null),!l)return;let{session:b,file:S}=l,{model:k}=b;$n.current=null;let E=vt.current,D=await mu(ei(fo,b.sceneConfig));await gi(D.product);let F=await Qo(b.bindings);if(await hr(D),vt.current!==E)return;let K=new Map,{parkedModels:le,mergedModelSources:te}=await Og(l.parkedFiles,l.mergeFiles,K);if(vt.current!==E){le.forEach(ci),te.forEach(On);return}let ke=fe=>{let ot=new Map;ot.set(Ut(k),fe),le.forEach(jt=>{jt.sessionModel&&ot.set(Ut(jt.sessionModel),jt.url)});let Et=(b.modelOrder??[]).map(jt=>ot.get(jt)).filter(jt=>!!jt),Tl=new Set(Et);for(let jt of[fe,...le.map(Fg=>Fg.url)])Tl.has(jt)||(Et.push(jt),Tl.add(jt));return Et},ct=()=>{for(let[fe,ot]of K)Zt.current.set(fe,ot),r?Ii.current.delete(fe):Ii.current.add(fe)},we;if(k.kind==="file"){if(!S){le.forEach(ci),te.forEach(On);return}let fe=vt.current,ot;try{ot=await ho(S)}catch(Et){console.warn("[BindingBuilder] Could not read the saved model:",Et),W(ms(k.name)),X("error"),le.forEach(ci),te.forEach(On);return}if(vt.current!==fe){ot.cleanup(),le.forEach(ci),te.forEach(On);return}Je.current?.cleanup(),Je.current=ot,we=ot.url,K.set(k.key,S),ct(),zr(),H.forEach(Et=>Et.resolved?.cleanup()),de(le),so(te),Q(ke(we)),Ve.reset(b.composition?Fo(b.composition):Do),an([])}else{we=k.url,ct(),zr(),H.forEach(ot=>ot.resolved?.cleanup()),de(le),so(te),Q(ke(we)),Ve.reset(b.composition?Fo(b.composition):Do),an([]);let fe=Qt.current;if(we===P&&fe?.url===we&&!tt.current){qe.current={model:k},ie.reset(Xo(fe.scene,F,te,pi(fe.scene,F).bindings)),Be.reset(D),W(`Restored your last session with ${k.name}.`),X("success");return}Je.current?.cleanup(),Je.current=null}qe.current={model:k,file:S??void 0},k.kind==="file"&&!r&&Ii.current.add(k.key);let Ot=++vt.current;we!==P&&Nt.clearAnimations(),qt(!0),Ro(null),bo.current=0,Le.current&&(clearTimeout(Le.current),Le.current=null),ji.current=S?.size,W("Restoring your last session."),X("default"),I(k.name),Ne({url:we,name:k.name}),pn(null),Ce(null),Qt.current=null,ie.reset({}),Be.reset(D),tt.current={requestId:Ot,modelName:k.name,modelUrl:we,storedBindings:F,restoring:!0},$(we)};ze(()=>{let r=l=>{if((l.metaKey||l.ctrlKey)&&l.key.toLowerCase()==="k"){l.preventDefault(),Mr(S=>!S);return}if(l.metaKey||l.ctrlKey||l.altKey||Pu(l.target,!0))return;if(l.key==="?"){l.preventDefault(),Pr(S=>!S);return}if(!P)return;let b=sr.find(S=>S.shortcut.toLowerCase()===l.key.toLowerCase());b?(l.preventDefault(),Bi(b.id)):l.key.toLowerCase()==="f"&&(l.preventDefault(),L?_n(L):Kn())};return window.addEventListener("keydown",r),()=>window.removeEventListener("keydown",r)},[P,L,_n,Kn]);let bn=Zc();if(Hn.status==="checking")return R("div",{className:"bb-root bb-root--licenseChecking",children:!u&&R(la,{title:"Validating license key\u2026"})});if(Hn.status==="invalid")return R("div",{className:"bb-root bb-root--licenseInvalid",children:R(la,{tone:"error",title:"Invalid license",message:Hn.isLocalDomain?Hn.reason??"License has been revoked or has expired":"Failed to load. Please contact the site administrator."})});let Ml=(Tt==="annotations"||wr.open&&ki==="cinematic")&&Pe?{position:Pe.position,target:Pe.target,azimuthAngle:Pe.azimuthAngle,polarAngle:Pe.polarAngle,fov:Pe.fov,zoom:Pe.zoom}:null,zg=P?eo.get(P)??"Model":"Untitled scene",Lo=Oe&&!Cu.find(r=>r.id===Ms)?.group?"general":Ms,Lg=r=>{r.panel==="object"?(Wt.setOpen(!0),on("object"),Ps(r.tab)):r.panel==="scene"?(Wt.setOpen(!0),on("scene"),Tr(r.tab)):r.panel==="configure"?(on("configure"),No("scene")):r.panel==="left"?(co.setOpen(!0),Sr(r.tab)):(Cs(r.tab),wr.setOpen(!0)),r.section&&bp(r.section)},Dg=()=>[...sr.map(r=>({id:`tool-${r.id}`,label:`${r.label} tool`,hint:"Tool",shortcut:r.shortcut,run:()=>Bi(r.id)})),{id:"frame",label:"Frame selection",hint:"Camera",shortcut:"F",run:()=>{L?_n(L):Kn()}},{id:"fit",label:"Fit scene",hint:"Camera",run:()=>{Kn()}},{id:"reset-view",label:"Reset view",hint:"Camera",run:()=>{Sl()}},{id:"code",label:"Show code",hint:"Code panel",keywords:"json typescript export",run:()=>{Wt.setOpen(!0),kr(!0)}},{id:"compare",label:"Compare before and after",hint:"Preview",run:()=>Vs(!0)},{id:"shortcuts",label:"Keyboard shortcuts",hint:"Help",shortcut:"?",run:()=>Pr(!0)},...f?[{id:"add-model",label:"Add model",hint:"Model",keywords:"upload import asset",run:ea}]:[],...up.map(r=>({id:`setting-${r.label}-${r.where.tab}`,label:r.label,hint:r.hint,keywords:r.keywords,run:()=>Lg(r.where)}))],Pl=[{title:"Scene settings",description:"Lighting, camera, and environment for the active model. No model files or bindings.",onImport:sg,onExportJson:()=>vl("json"),onExportTs:()=>vl("ts"),importDisabled:!Ht.length||Me,exportDisabled:!Ht.length||Me},{title:"Object bindings",description:"Bindings for the active model, with uploaded textures when available. No model files or scene settings.",onImport:rg,onExportJson:()=>xl("json"),onExportTs:()=>xl("ts"),importDisabled:!Ht.length||Me,exportDisabled:!Ht.length||Me}],Bl=f&&nt(Eo,"sceneBundle")?{onImport:()=>_s.current?.click(),onExport:Ig,importDisabled:Me,exportDisabled:Me||!me.length||me.some(r=>!r.ready)}:void 0,ra=Ge?R(et,{children:"Click the preview to look around \xB7 Esc to release"}):Xt!=="select"&&!L?R(et,{children:"Select an object to transform it"}):Xt==="move"?R(et,{children:"Drag an arrow or plane to move"}):Xt==="rotate"?R(et,{children:"Drag a ring to rotate"}):Xt==="scale"?R(et,{children:"Drag the handle to scale"}):db&&Ar?ae(et,{children:[ae("span",{children:[R("kbd",{children:"W"}),R("kbd",{children:"A"}),R("kbd",{children:"S"}),R("kbd",{children:"D"})," move"]}),ae("span",{children:["\xB7 ",R("kbd",{children:"Space"}),"/",R("kbd",{children:"C"})," up \xB7 down"]}),R("span",{children:"\xB7 drag to look"})]}):null;return ae(od.Provider,{value:gb,children:[ae("div",{className:"bb-root","data-input":"pointer",onPointerDownCapture:r=>{r.currentTarget.dataset.input="pointer"},onKeyDownCapture:r=>{r.key==="Tab"&&(r.currentTarget.dataset.input="keyboard")},onMouseOver:bn.onMouseOver,onContextMenu:bn.onContextMenu,onKeyDown:r=>{r.key!=="Escape"||r.defaultPrevented||!Oe||r.target.closest('input:not([type="checkbox"]), textarea, select, [contenteditable="true"]')||(r.preventDefault(),r.stopPropagation(),tn?hs():xs())},children:[R("input",{ref:v,type:"file",accept:sa,className:"bb-hiddenInput",onChange:Kb,disabled:Me}),R("input",{ref:m,type:"file",accept:sa,className:"bb-hiddenInput",onChange:Jb,disabled:Me}),R("input",{ref:A,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:ag,disabled:Me}),R("input",{ref:G,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:lg,disabled:Me}),R("input",{ref:_s,type:"file",accept:".zip,application/zip",hidden:!0,onChange:async r=>{let l=r.target.files?.[0];r.target.value="",l&&await kl(l)}}),R(Yc,{modelName:zg,modelMenu:f||me.length>1?r=>R(Zd,{close:r,models:me.length>1?me.map(l=>({url:l.url,label:eo.get(l.url)??l.name})):void 0,activeModelUrl:P,onSelectModel:zo,onRestore:!f||P||c?void 0:Ag,restoreDisabled:Me,onAddModel:f&&P?ea:void 0,onUpload:f&&!P?hl:void 0,addModelDisabled:Me,onReset:f&&P?()=>Mg(Ln):void 0,resetLabel:`Reset ${Mu[Ln]} changes\u2026`,onRemove:f&&P&&(!c||Vn.length>1)?Gb:void 0,confirmRemove:Vn.length<=1}):void 0,canUndo:Io.canUndo,canRedo:Io.canRedo,undoTarget:Mu[Ln],onUndo:Io.undo,onRedo:Io.redo,tool:Xt,onToolChange:r=>{Bi(r),r!=="select"&&No("bindings")},space:$s,onSpaceChange:ob,hasModel:!!P,compareOpen:Oo,onToggleCompare:()=>{Vs(r=>!r),Dr(null)},codeOpen:Bs,onToggleCode:()=>kr(r=>!r),onOpenCommands:()=>Mr(!0),start:e,xrToolsSlot:Vu,fileActions:ae(et,{children:[R(Wc,{scopes:Pl,sceneBundle:Bl,busy:sn||ys}),R(qc,{scopes:Pl,sceneBundle:Bl,busy:sn||ys})]})}),ae("div",{className:`bb-workspace ${po?"bb-workspace--customerPreview":""}`,children:[co.open?ae(et,{children:[ae("aside",{className:"bb-panel bb-panel--left",style:{width:co.size},onPointerDownCapture:()=>{Tt==="assets"&&No("assets"),Tt==="annotations"&&No("scene")},children:[ae("div",{className:"bb-tabs",role:"tablist","aria-label":"Scene contents",children:[Zx.filter(r=>r.id!=="assets"||f).map(r=>R("button",{type:"button",role:"tab","aria-selected":Tt===r.id,className:`bb-tab ${Tt===r.id?"bb-tab--active":""}`,onClick:()=>Sr(r.id),children:r.label},r.id)),R("span",{className:"bb-topBarSpacer"}),R("button",{type:"button",className:"bb-toolButton bb-toolButton--small","aria-label":"Hide left panel",title:"Hide panel",onClick:()=>co.setOpen(!1),children:R(Fx,{size:14})})]}),R("div",{className:`bb-panelBody ${Tt==="outliner"?"bb-panelBody--fill":""}`,children:Tt==="outliner"?R(Fp,{bindings:q,selectedItem:L,onSelect:oa,onHover:yg,modelGroups:Ab,onSelectModel:zo,isolatedItem:hi,onIsolate:In,multiSelectEnabled:tn,onToggleMultiSelect:Tu,onExitMultiSelect:hs,multiSelectedKeys:_e,onSetMultiSelected:xg,hierarchy:yb,selectionSets:ee.selectionSets,onSelectionSetsChange:nb}):P?Tt==="assets"?R(Aa,{assets:me.map(r=>({...r,displayName:eo.get(r.url)})),activeUrl:P,composition:rt,busy:sn||Me,onFrameAll:()=>{let r=new Su;for(let b of me){if(b.placement.visible===!1)continue;let S=yt.current.get(b.url);S&&(S.updateWorldMatrix(!0,!0),r.union(new Su().setFromObject(S)))}let l=jo.current;!r.isEmpty()&&l&&(bd(r,l.raw.controls),l.raw.controls.fitToBox(r,!0,gd).then(()=>l.invalidate()))},onSelect:zo,onAdd:ea,addRequiresTier:el?void 0:Ho("models",me.length),onChange:ia,onGridSize:r=>Ve.setValue(l=>({...l,gridSize:r})),onDuplicate:r=>{Eg(r)},onDelete:c?()=>rn(!0):jg,deleteIsPermanent:!!c,onSnap:r=>ia(r,Dl(rt.placements[r]??{},rt.gridSize)),onGround:r=>{let l=yt.current.get(r),b=l?Hl(l):null;b&&ia(go.get(r),Fl(Un(r),b))}}):Tt==="annotations"?R(Gx,{config:ee,onChange:Rt,cameraState:Ml,onPreviewView:pl}):R("div",{ref:As,className:"bb-measurePanel"}):R("p",{className:"bb-panelEmpty",children:"Open a model to use this."})})]}),R(ii,{orientation:"vertical",label:"Resize left panel",onPointerDown:co.startResize,onKeyDown:co.onResizeKey})]}):R("button",{type:"button",className:"bb-panelReveal bb-panelReveal--left","aria-label":"Show left panel",title:"Show panel",onClick:()=>co.setOpen(!0),children:R(Hx,{size:14})}),ae("main",{className:"bb-previewShell",children:[ae("div",{className:"bb-preview",ref:N,onPointerDownCapture:r=>{mi.current={shiftKey:r.shiftKey,ctrlKey:r.ctrlKey,metaKey:r.metaKey}},onKeyDownCapture:()=>{mi.current={shiftKey:!1,ctrlKey:!1,metaKey:!1}},onFocus:r=>{r.currentTarget.contains(r.relatedTarget)||_r()},children:[P?ae("div",{className:"bb-viewportBar",children:[R(Zn,{label:"View",icon:R(Dx,{size:13,"aria-hidden":"true"}),title:"Preview options",children:()=>ae(et,{children:[ae("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Ds,onChange:r=>Wu(r.target.checked)}),"Zoom on selected"]}),ae("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Nr,onChange:r=>Yu(r.target.checked)}),"Highlight on hover"]}),ae("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Ar,onChange:r=>Ju(r.target.checked)}),"Camera controls"]}),ae("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Cr,onChange:r=>Du(r.target.checked)}),"Floor grid"]})]})}),ae("label",{className:"bb-topBarSelect",title:"Renderer","data-ri-path":"sceneConfig.model.renderer",children:[R("span",{className:"bb-visuallyHidden",children:"Renderer"}),ae("select",{value:ee.model.renderer,onChange:r=>Rt({...ee,model:{...ee.model,renderer:r.target.value}}),children:[R("option",{value:"pbr",children:"PBR"}),R("option",{value:"matcap",children:"Matcap"}),R("option",{value:"uv-checker",children:"UV checker"})]}),R(jx,{size:12,"aria-hidden":"true"})]})]}):null,R(rd,{visible:Me,title:w||void 0,message:vr,progress:mb??void 0}),P&&R("div",{className:`bb-canvasHint ${ra?"bb-canvasHint--visible":""} ${Oo?"bb-canvasHint--belowCompare":""}`,"aria-hidden":!ra,children:ra}),po?R("button",{type:"button",className:"bb-customerPreviewExit",onClick:()=>Br(!1),children:"Previewing as a customer \xB7 Exit"}):null,P?R(ba,{loading:"eager",enableXR:!0,arHandoff:o,mobileHandoffUrl:n,modelUrl:P,tilesetUrl:j?.tilesetUrl,models:Ob,onModelChange:zo,onExtraModelLoaded:ig,onExtraModelError:ng,mergeModels:Yr,onMergeModelLoaded:tg,onMergeModelError:og,originalNodePoses:xt.current,objectBindings:q,comparisonHighlights:Ks?.after,selectedObject:Se,selectedObjectRefs:Cb,selectedObjectOutlineColor:"#35c0dc",onObjectSelect:vg,onSelectionClear:xs,onObjectBindingsChange:To,onTextureUpload:zb,onObjectEditLeaseChange:(r,l)=>T?.(`${P}|${r.modelObjectId||r.id}`,l),showObjectBindingDataPanel:!1,showSceneObjectsPanel:!1,onCameraChange:Bb,onViewerReady:r=>{jo.current=r,kb(r.raw.nodes),Mb(r)},onAnnotationsChange:jb,activeAnnotation:ub?.annotation??null,onActiveAnnotationChange:Ib,onSequencesReady:Sb,showSequenceControls:!1,sequenceAutoPlay:!1,onAnimationsReady:Vb,onModelAnimationsReady:At.handleModelAnimationsReady,onSceneLoaded:Hb,onAssetDiagnostics:qr?r=>ol({url:P,report:r}):void 0,onRuntimeStats:qr?nl:void 0,onLoadError:Ub,onObjectCatalog:j?.tilesetUrl?$b:void 0,onProgress:_b,onCameraControllerChange:$r,cameraControllerType:Gs,onTexturePositioningChange:cb,endTexturePositioningRef:Ys,licenseKey:i,licenseValidationUrl:a,dracoDecoderPath:d,ktx2TranscoderPath:s,meshopt:p,sceneConfig:Rb,onSceneConfigChange:Nb,productOptions:po?!0:void 0,preserveDrawingBuffer:!0,disableZoom:!1,zoomOnSelected:Ds,highlightOnHover:Nr,enableCameraControls:Ar,moveModeEnabled:eb,scaleModeEnabled:tb,gizmoTool:Xt==="rotate"?"rotate":"move",showFloorGrid:Cr&&!po,objectTransformSpace:$s,enableKeyboardNavigation:!0,showViewGizmo:!po,showMeasureTools:!0,measurementModelId:qe.current?.model.kind==="file"?Ut(qe.current.model):void 0,showSectionTools:!0,isolation:Nu,onIsolationChange:()=>In(null),showIsolateControls:!0,decalMove:gg,onDecalDoubleClick:hg,panelHoveredObject:Nr?bb:null,showLoadingOverlay:!1,autoRotate:Ge?!1:ee.model.autoRotate??!1,autoRotateSpeed:ee.model.autoRotateSpeed??1}):R("div",{className:`bb-previewPlaceholder ${Lu?"bb-previewPlaceholder--dragActive":""}`,onDragEnter:dg,onDragOver:cg,onDragLeave:pg,onDrop:ug,children:ae("div",{className:"bb-dropCard",children:[R(Ex,{size:18,"aria-hidden":"true"}),R("h3",{children:"Drop a model to start"}),R("p",{children:"Each object becomes a binding you can edit and export as code."}),R("div",{className:"bb-formatChips","aria-label":"Supported formats",children:["GLB","GLTF","OBJ","FBX","USDZ","STL","PLY","ZIP"].map(r=>R("span",{children:r},r))}),f?R("button",{type:"button",className:"bb-button bb-button--primary",onClick:hl,disabled:Me,children:"Choose file"}):null]})}),P&&Oo?R(tc,{showOutlines:Lr,onShowOutlinesChange:sb,matchBy:Fr,onMatchByChange:r=>{lb(r),Hr(null)},report:Fn??void 0,selected:Ri,onSelect:r=>{Hr(r?.id??null),r?.afterKey&&oa(r.afterKey)},liveViewerRef:jo,split:rb,onSplitChange:ab,labels:[dn?"Pinned":"Before","Now"],beforeAction:ae("button",{type:"button",className:"ri-compare__labelAction",onClick:()=>Dr(r=>r?null:{bindings:q,sceneConfig:ee}),"aria-pressed":!!dn,title:dn?"Unpin: compare with the project as it was opened again":"Pin as before: compare later changes with how the preview looks now",children:[dn?R(Vx,{size:12}):R(_x,{size:12}),dn?"Unpin":"Pin"]}),renderBefore:r=>R(ba,{loading:"eager",modelUrl:P,tilesetUrl:j?.tilesetUrl,comparisonHighlights:Ks?.before,objectBindings:cn.bindings,sceneConfig:{...cn.sceneConfig,section:ee.section},licenseKey:i,licenseValidationUrl:a,dracoDecoderPath:d,ktx2TranscoderPath:s,meshopt:p,preset:"minimal",showFloorGrid:Cr,showLoadingOverlay:!1,showObjectNavigator:!1,selectedObject:null,zoomOnSelected:!1,highlightOnHover:!1,autoRotate:!1,cinematic:!1,onViewerReady:r})}):null]}),R(wu,{panel:wr,tabs:Qx,tab:ki,onTabChange:Cs,hasModel:!!P,onPointerDownCapture:()=>No("scene"),children:ki==="sequences"?R(Wx,{config:ee,onChange:Rt,controls:wb,bindings:q,clipDetails:Nt.clipDetails}):ki==="clips"?R(qx,{config:Li.config?{...ee,animations:Li.config}:ee,onChange:Li.onChange?r=>Li.onChange?.(r.animations):Rt,clipDetails:At.clipDetails,active:At.active,play:At.play,pause:At.pause,stop:At.stop,setSpeed:At.setSpeed,seek:At.seek}):nt(Eo,"cinematic")?R(Yx,{config:ee,onChange:Rt,cameraState:Ml,onPreviewWaypoint:pl}):R(We,{requiredTier:"starter",feature:"Cinematic"})})]}),Wt.open?ae(et,{children:[R(ii,{orientation:"vertical",label:"Resize inspector",onPointerDown:Wt.startResize,onKeyDown:Wt.onResizeKey}),ae("aside",{className:"bb-panel bb-panel--right",style:{width:Wt.size},onPointerDownCapture:()=>No(ht!=="object"?"scene":"bindings"),children:[ae("div",{className:"bb-inspectorScope",children:[R("div",{className:"bb-scopeSwitch",role:"tablist","aria-label":"What to edit",children:["object","scene","configure"].map(r=>R("button",{type:"button",role:"tab","aria-selected":ht===r,className:ht===r?"is-active":"",onClick:()=>{on(r),No(r==="object"?"bindings":"scene")},children:r==="object"?"Object":r==="scene"?"Scene":"Configure"},r))}),R("button",{type:"button",className:"bb-toolButton bb-toolButton--small","aria-label":"Hide inspector",title:"Hide panel",onClick:()=>Wt.setOpen(!1),children:R($x,{size:14})})]}),ht==="configure"?P?R("section",{className:"bb-editor",children:R(Jx,{config:ee,onChange:Be.setValueAsStep,objectBindings:q,materialVariantGroups:il,selectedKey:L,previewSelections:Ci,onPreviewChange:Rs,onPreviewAsCustomer:()=>Br(!0),publish:t,modelFileName:w})}):R("p",{className:"bb-panelEmpty",children:"Open a model to let customers customise it."}):ht==="scene"?P?ae(et,{children:[R("div",{className:"bb-tabs",role:"tablist","aria-label":"Scene settings",children:Fc.map(r=>R("button",{type:"button",role:"tab","aria-selected":nn===r.id,className:`bb-tab ${nn===r.id?"bb-tab--active":""}`,onClick:()=>Tr(r.id),children:r.label},r.id))}),R("section",{className:"bb-editor",children:R(Na,{diagnostics:{report:tl?.url===P?tl.report:null,runtimeStats:xb,onRefresh:vb,onSelectObject:r=>{let l=Object.keys(q).find(b=>b===r||q[b].modelObjectId===r);l&&oa(l)}},onDiagnosticsOpenChange:hb,config:ee,onChange:Rt,activeSubTab:nn,materialVariantGroups:il,onImageFile:wl,objectBindings:q})})]}):R("p",{className:"bb-panelEmpty",children:"Open a model to edit its scene."}):!Se||!L?R("p",{className:"bb-panelEmpty",children:P?"Select an object to edit it.":"Open a model, then select an object to edit it."}):ae(et,{children:[ae("div",{className:"bb-objectHeader",children:[ae("div",{className:"bb-objectHeaderText",children:[R("h2",{children:Oe&&_e.length>1?`${_e.length} objects`:Se.label||L}),R("code",{title:Oe?void 0:Se.modelObjectId,children:Oe&&_e.length>1?"Edits apply to all of them":Se.id})]}),R(Zn,{icon:R(Lx,{size:14,"aria-hidden":"true"}),title:"Object actions",align:"right",children:r=>ae(et,{children:[ae("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>{r(),Ru({name:Se.label||L,style:kd(Se)})},children:[R(zx,{size:13,"aria-hidden":"true"}),"Copy style"]}),ae("button",{type:"button",className:"bb-headerMenuItem",disabled:!jn,title:jn?`Copied from ${jn.name}`:void 0,onClick:()=>{if(r(),!jn)return;let l=Oe?_e:[L];ie.setValueAsStep(b=>Cd(b,l,jn.style))},children:[R(Ix,{size:13,"aria-hidden":"true"}),"Paste style",Oe&&_e.length>1?` to ${_e.length}`:""]}),ae("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{r(),Bg(Oe&&_e.length>0?_e:[L])},children:[R(Kx,{size:13,"aria-hidden":"true"}),Oe&&_e.length>1?`Delete ${_e.length} objects\u2026`:"Delete object\u2026"]})]})})]}),R("div",{className:"bb-tabs",role:"tablist","aria-label":"Object settings",children:Cu.filter(r=>!Oe||r.group).map(r=>R("button",{type:"button",role:"tab","aria-selected":Lo===r.id,className:`bb-tab ${Lo===r.id?"bb-tab--active":""}`,onClick:()=>Ps(r.id),children:r.label},r.id))}),ae("section",{className:"bb-editor",children:[Lo==="general"&&ae(et,{children:[!Oe&&R(wp,{selectedItem:L,selectedBinding:Se,open:Yt.identity,onToggle:()=>Jt("identity"),updateBinding:wt,idError:Lb}),!Oe&&R(kp,{selectedItem:L,selectedBinding:Se,open:Yt.basics,onToggle:()=>Jt("basics"),updateBinding:wt}),Oe&&R(Ye,{title:"Basics",open:Yt.basics,onToggle:()=>Jt("basics"),children:R("div",{className:"bb-groupFlags",children:["selectable","hoverable","visible"].map(r=>R(Xx,{label:r.charAt(0).toUpperCase()+r.slice(1),values:_e.map(l=>q[l]).filter(l=>l&&!l.removed).map(l=>l[r]!==!1),onChange:l=>ie.setValueAsStep(b=>{let S={...b};for(let k of _e)b[k]&&!b[k].removed&&(S[k]={...b[k],[r]:l});return S})},r))})}),R(jp,{selectedItem:L,selectedBinding:Se,open:Yt.transform,onToggle:()=>Jt("transform"),updateBinding:wt,originalTransform:xt.current[L]??null,originalTransforms:xt.current}),!Oe&&R(Np,{selectedBinding:Se,open:Yt.camera,onToggle:()=>Jt("camera"),cameraState:Pe,formattedCameraState:Eb,savedCameraPosition:mo,onSaveCameraPosition:wg,onGoToSavedCamera:Sg,onClearSavedCamera:kg,onResetView:Sl,onFitScene:Kn})]}),Lo==="material"&&ae("div",{className:"bb-singleSection",children:[R(yp,{disabled:!L,onApply:r=>L&&Xr(L,l=>({...l,...r}))}),R(xp,{selectedItem:L,selectedMaterial:Wr,pbrWorkflow:Ku,onPbrWorkflowChange:Gu,openMaterialPanels:$u,materialPanelEnabled:qu,onToggleMaterialPanel:_u,onSetMaterialPanelState:Fb,updateSelectedMaterial:Xr,setSelectedTexturePath:Db,isTexturePositioningEnabled:pb,onConfirmTexturePosition:Cg,takesImage:bl})]}),Lo==="decals"&&R("div",{className:"bb-singleSection",children:!Oe&&R(Rp,{selectedItem:L,selectedBinding:Se,open:Yt.decals,onToggle:()=>Jt("decals"),updateBinding:wt,placement:xi,onPlacementChange:fg,defaultSize:bg,onImageFile:wl,onNudge:mg})}),Lo==="actions"&&R("div",{className:"bb-singleSection",children:!Oe&&R(Mp,{selectedItem:L,selectedBinding:Se,open:Yt.actions,onToggle:()=>Jt("actions"),updateBinding:wt,takesImage:bl})}),Lo==="data"&&ae(et,{children:[R(Ja,{title:"Metrics",label:"Metrics JSON",open:Yt.metrics,onToggle:()=>Jt("metrics"),draft:Ss,error:Iu,example:'{"area": 42}',onDraftChange:vi,onCommit:()=>yl("metrics",Ss,wi)}),R(Ja,{title:"Metadata",label:"Metadata JSON",open:Yt.metadata,onToggle:()=>Jt("metadata"),draft:ks,error:zu,example:'{"room": "kitchen"}',onDraftChange:yi,onCommit:()=>yl("metadata",ks,Si)})]})]})]}),Bs?R(sp,{scope:ht==="object"?"object":"scene",selectedKey:L,selectedBinding:Se??null,sceneConfig:ee,sceneTab:ht==="configure"?"product":nn,onClose:()=>kr(!1)}):null]})]}):R("button",{type:"button",className:"bb-panelReveal bb-panelReveal--right","aria-label":"Show inspector",title:"Show panel",onClick:()=>Wt.setOpen(!0),children:R(Ux,{size:14})})]}),R(ep,{saveState:Fi&&P?"Saved in this browser":void 0,objectCount:Ht.filter(r=>!q[r]?.removed).length,selectedCount:Oe?_e.length:L?1:0,path:bn.path,hints:ev}),R(np,{toast:Eu,onDismiss:ju}),bn.menu?R(Qc,{...bn.menu,onClose:bn.closeMenu}):null,Fu?R(cp,{commands:Dg(),onClose:()=>Mr(!1)}):null,Hu?R(pp,{onClose:()=>Pr(!1)}):null]}),Xu&&R(su,{target:Dn,onCancel:$i,onConfirm:Pg}),Ao&&R(lu,{models:[{name:Ao.session.model.name,mergedCount:Ao.session.mergeModels?.length??0},...(Ao.session.parkedModels??[]).map(r=>({name:r.model.name,mergedCount:r.mergeModels?.length??0}))],savedAt:Ao.session.savedAt,onCancel:Ng,onConfirm:()=>{let{name:r}=Ao.session.model;Cl().catch(l=>{console.warn("[BindingBuilder] Could not restore the session:",l),W(ms(r)),X("error")})}}),Zu&&R(cu,{destinations:Vn.filter(r=>r.kind==="model"),onCancel:Xb,onChoose:Zb}),Qu&&R(pu,{options:Vn,onCancel:qb,onRemoveModel:Wb,onRemoveMerge:Yb,permanent:!!c,onRemoveAll:c?void 0:()=>{rn(!1),Hi()}}),uo&&R(du,{nodeLabel:uo.length===1?q[uo[0]]?.label||uo[0]:`${uo.length} objects`,count:uo.length,onCancel:Tg,onConfirm:Rg})]})}export{er as a,xv as b,tv as c};
|
|
3
|
+
`)}function ip(e,t,i){fn(new Blob([t],{type:i}),e)}function ja(e){return JSON.stringify(e??{},null,2)}function Ia(e){return`[${e[0].toFixed(3)}, ${e[1].toFixed(3)}, ${e[2].toFixed(3)}]`}import{jsx as zt,jsxs as ap}from"react/jsx-runtime";var $f={model:["model","wireframe"],camera:["camera"],world:["environment","background","groundShadows"],lighting:["lighting","shadows"],postProcessing:["postProcessing"],rules:["styleRules"],product:["product"]};function Uf(e){return!e||typeof e!="object"?e:Object.fromEntries(Object.entries(e).filter(([,t])=>t?.enabled))}var sp=zf(function({scope:t,selectedKey:i,selectedBinding:a,sceneConfig:o,sceneTab:n,onClose:d}){let[s,p]=rp("ts"),[c,x]=rp(!1),{preview:h,full:g,caption:C}=Lf(()=>{if(t==="object"){if(!i||!a)return{preview:"",full:"",caption:"Select an object to see its binding."};let T={[i]:a};return{preview:ri(T),full:s==="ts"?cr(T):ri(T),caption:"objectBindings"}}let M=$f[n]??[],y=Object.fromEntries(M.map(T=>[T,T==="postProcessing"?Uf(o[T]):o[T]]));return{preview:JSON.stringify(y,null,2),full:s==="ts"?ur(o):pr(o),caption:"sceneConfig"}},[t,i,a,o,n,s]);return ap("section",{className:"bb-codePanel","aria-label":"Code",children:[ap("header",{children:[zt("strong",{children:"Code"}),zt("code",{children:C}),zt("span",{className:"bb-topBarSpacer"}),zt("div",{className:"bb-codeFormat",role:"radiogroup","aria-label":"Code format",children:["ts","json"].map(M=>zt("button",{type:"button",role:"radio","aria-checked":s===M,className:s===M?"is-active":"",onClick:()=>p(M),children:M==="ts"?"TS":"JSON"},M))}),zt("button",{type:"button",className:"bb-toolButton bb-toolButton--small",disabled:!g,title:t==="scene"?"Copy the whole scene config":"Copy this binding","aria-label":t==="scene"?"Copy the whole scene config":"Copy this binding",onClick:async()=>{await lr(g),x(!0),window.setTimeout(()=>x(!1),1500)},children:c?zt(Df,{size:13}):zt(Ff,{size:13})}),zt("button",{type:"button",className:"bb-toolButton bb-toolButton--small","aria-label":"Close code panel",onClick:d,children:zt(Hf,{size:13})})]}),zt("pre",{tabIndex:0,children:h})]})});import{useEffect as za,useMemo as _f,useRef as dp,useState as lp}from"react";import{Search as Vf}from"lucide-react";import{jsx as Lt,jsxs as qo}from"react/jsx-runtime";function Kf(e,t){let i=e.label.toLowerCase(),a=`${i} ${e.hint} ${e.keywords??""}`.toLowerCase(),o=0;for(let n of t){if(!a.includes(n))return-1;o+=i.startsWith(n)?3:i.includes(n)?2:1}return o}function cp({commands:e,onClose:t}){let[i,a]=lp(""),[o,n]=lp(0),d=dp(null),s=_f(()=>{let c=i.toLowerCase().split(/\s+/).filter(Boolean);return c.length?e.map(x=>({command:x,value:Kf(x,c)})).filter(x=>x.value>=0).sort((x,h)=>h.value-x.value).slice(0,40).map(x=>x.command):e.slice(0,40)},[e,i]);za(()=>n(0),[i]),za(()=>{d.current?.children[o]?.scrollIntoView({block:"nearest"})},[o]);let p=c=>{c&&(t(),c.run())};return Lt("div",{className:"bb-paletteBackdrop",onMouseDown:c=>{c.target===c.currentTarget&&t()},children:qo("div",{className:"bb-palette",role:"dialog","aria-modal":"true","aria-label":"Search settings",children:[qo("label",{className:"bb-paletteSearch",children:[Lt(Vf,{size:14,"aria-hidden":"true"}),Lt("input",{autoFocus:!0,role:"combobox","aria-expanded":"true","aria-controls":"bb-paletteList","aria-activedescendant":s[o]?`bb-palette-${s[o].id}`:void 0,"aria-label":"Search settings and commands",placeholder:"Search settings and commands",value:i,onChange:c=>a(c.target.value),onKeyDown:c=>{c.key==="ArrowDown"&&(c.preventDefault(),n(x=>Math.min(s.length-1,x+1))),c.key==="ArrowUp"&&(c.preventDefault(),n(x=>Math.max(0,x-1))),c.key==="Enter"&&(c.preventDefault(),p(s[o])),c.key==="Escape"&&(c.preventDefault(),c.stopPropagation(),t())}})]}),qo("div",{className:"bb-paletteList",id:"bb-paletteList",role:"listbox",ref:d,children:[s.map((c,x)=>qo("button",{id:`bb-palette-${c.id}`,type:"button",role:"option","aria-selected":x===o,tabIndex:-1,className:x===o?"is-active":"",onMouseMove:()=>n(x),onClick:()=>p(c),children:[Lt("span",{children:c.label}),c.shortcut?Lt("kbd",{children:c.shortcut}):null,Lt("small",{children:c.hint})]},c.id)),s.length?null:qo("p",{children:["Nothing matches \u201C",i,"\u201D."]})]})]})})}function pp({onClose:e}){let t=dp(null);return za(()=>t.current?.focus(),[]),Lt("div",{className:"bb-paletteBackdrop",onMouseDown:a=>{a.target===a.currentTarget&&e()},children:Lt("div",{ref:t,tabIndex:-1,className:"bb-shortcuts",role:"dialog","aria-modal":"true","aria-label":"Keyboard shortcuts",onKeyDown:a=>{(a.key==="Escape"||a.key==="?")&&(a.preventDefault(),a.stopPropagation(),e())},children:[["Tools",[["V","Select"],["G","Move"],["R","Rotate"],["T","Scale"],["F","Frame selection"]]],["Editor",[["\u2318K","Search settings"],["\u2318Z","Undo"],["\u21E7\u2318Z","Redo"],["?","Shortcuts"],["Esc","Clear selection"]]],["Camera",[["W A S D","Move"],["Space / C","Up and down"],["Arrows","Orbit"],["\u21E7 Up / Down","Zoom"]]],["Selecting",[["Click","Select"],["\u2318 Click","Add or remove"],["\u21E7 Click","Add in the viewport, range in the Outliner"],["\u2318A","All shown in the Outliner"]]]].map(([a,o])=>qo("section",{children:[Lt("h4",{children:a}),o.map(([n,d])=>qo("div",{children:[Lt("span",{children:d}),Lt("kbd",{children:n})]},d))]},a))})})}var je=(e,t)=>({panel:"object",tab:e,section:t}),ue=(e,t)=>({panel:"scene",tab:e,section:t}),up=[{label:"Object ID",hint:"Object \u203A General",keywords:"identity id modelObjectId",where:je("general","Identity")},{label:"Label, type, status, group, tags",hint:"Object \u203A General",keywords:"basics selectable hoverable visible",where:je("general","Basics")},{label:"Position, rotation, scale",hint:"Object \u203A General",keywords:"transform move pivot",where:je("general","Transform")},{label:"Saved view",hint:"Object \u203A General",keywords:"camera position cameraState",where:je("general","Saved view")},{label:"Material presets",hint:"Object \u203A Material",keywords:"wood metal glass plastic",where:je("material")},{label:"Base color",hint:"Object \u203A Material",keywords:"pbr albedo texture metalness baseColor",where:je("material","Surface")},{label:"Roughness",hint:"Object \u203A Material",keywords:"glossiness matte shiny",where:je("material","Roughness")},{label:"Opacity",hint:"Object \u203A Material",keywords:"alpha transparency blending",where:je("material","Opacity")},{label:"Emission",hint:"Object \u203A Material",keywords:"emissive glow",where:je("material","Emission")},{label:"Normal and bump maps",hint:"Object \u203A Material",keywords:"normalMap bumpMap",where:je("material","Normal and bump")},{label:"Displacement",hint:"Object \u203A Material",keywords:"height map",where:je("material","Displacement")},{label:"Ambient occlusion map",hint:"Object \u203A Material",keywords:"aoMap",where:je("material","Ambient occlusion")},{label:"Clearcoat",hint:"Object \u203A Material",keywords:"lacquer gloss layer",where:je("material","Clearcoat")},{label:"Sheen",hint:"Object \u203A Material",keywords:"fabric velvet",where:je("material","Sheen")},{label:"Anisotropy",hint:"Object \u203A Material",keywords:"brushed metal",where:je("material","Anisotropy")},{label:"Transmission and volume",hint:"Object \u203A Material",keywords:"glass thickness attenuation",where:je("material","Transmission and volume")},{label:"Faces",hint:"Object \u203A Material",keywords:"side double backface",where:je("material","Faces")},{label:"Decals",hint:"Object \u203A Decals",keywords:"logo text image print",where:je("decals")},{label:"Actions",hint:"Object \u203A Actions",keywords:"onAction button command",where:je("actions")},{label:"Metrics",hint:"Object \u203A Data",keywords:"json",where:je("data","Metrics")},{label:"Metadata",hint:"Object \u203A Data",keywords:"json",where:je("data","Metadata")},{label:"Model rotation",hint:"Scene \u203A Model",keywords:"straighten orient",where:ue("model","Display")},{label:"Renderer and shading",hint:"Scene \u203A Model",keywords:"pbr matcap uv checker lit unlit normals",where:ue("model","Display")},{label:"Material variants",hint:"Scene \u203A Model",keywords:"KHR_materials_variants",where:ue("model","Display")},{label:"Auto rotate",hint:"Scene \u203A Model",keywords:"turntable spin",where:ue("model","Auto rotate")},{label:"Wireframe",hint:"Scene \u203A Model",where:ue("model","Wireframe")},{label:"Diagnostics",hint:"Scene \u203A Model",keywords:"asset statistics triangles textures",where:ue("model","Diagnostics")},{label:"Field of view",hint:"Scene \u203A Camera",keywords:"fov lens",where:ue("camera","Lens")},{label:"Environment",hint:"Scene \u203A World",keywords:"hdri preset intensity rotation ibl",where:ue("world","Environment")},{label:"Environment shadow",hint:"Scene \u203A World",keywords:"shadowLight",where:ue("world","Environment shadow")},{label:"Background",hint:"Scene \u203A World",keywords:"color image environment",where:ue("world","Background")},{label:"Ground shadows",hint:"Scene \u203A World",keywords:"contact catcher",where:ue("world","Ground shadows")},{label:"Lights",hint:"Scene \u203A Lights",keywords:"directional point spot hemisphere",where:ue("lighting","Lights")},{label:"Shadows",hint:"Scene \u203A Lights",keywords:"map size bias softness",where:ue("lighting","Shadows")},{label:"Effects",hint:"Scene \u203A Effects",keywords:"post processing bloom ssao tone mapping vignette depth of field",where:ue("postProcessing")},{label:"Tone mapping",hint:"Scene \u203A Effects",keywords:"post processing effect aces filmic exposure",where:ue("postProcessing","Tone mapping")},{label:"Brightness and contrast",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Brightness and contrast")},{label:"Hue and saturation",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Hue and saturation")},{label:"Vignette",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Vignette")},{label:"Bloom",hint:"Scene \u203A Effects",keywords:"post processing effect glow threshold",where:ue("postProcessing","Bloom")},{label:"Ambient occlusion (SSAO)",hint:"Scene \u203A Effects",keywords:"post processing effect ssao",where:ue("postProcessing","Ambient occlusion")},{label:"Depth of field",hint:"Scene \u203A Effects",keywords:"post processing effect bokeh blur focus",where:ue("postProcessing","Depth of field")},{label:"God rays",hint:"Scene \u203A Effects",keywords:"post processing effect sun",where:ue("postProcessing","God rays")},{label:"Lens flare",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Lens flare")},{label:"Outline",hint:"Scene \u203A Effects",keywords:"post processing effect edge",where:ue("postProcessing","Outline")},{label:"Anti-aliasing (SMAA)",hint:"Scene \u203A Effects",keywords:"post processing effect smaa",where:ue("postProcessing","Anti-aliasing")},{label:"Chromatic aberration",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Chromatic aberration")},{label:"Glitch",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Glitch")},{label:"Noise",hint:"Scene \u203A Effects",keywords:"post processing effect grain",where:ue("postProcessing","Noise")},{label:"Pixelation",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:ue("postProcessing","Pixelation")},{label:"Section cut",hint:"Scene \u203A Model",keywords:"clip plane box slice",where:ue("model","Section cut")},{label:"Configure: customer choices",hint:"Configure",keywords:"product configurator options swatch variant customise customize choices shop e-commerce",where:{panel:"configure",tab:"configure"}},{label:"Configure: prices and buying",hint:"Configure",keywords:"price sku checkout buy link cart currency commerce",where:{panel:"configure",tab:"configure",section:"Prices and buying"}},{label:"Configure: restrictions",hint:"Configure",keywords:"compatibility rules requires excludes combinations",where:{panel:"configure",tab:"configure",section:"Restrictions"}},{label:"Configure: publish and embed",hint:"Configure",keywords:"embed publish share website shopify wordpress",where:{panel:"configure",tab:"configure",section:"Publish"}},{label:"Rules",hint:"Scene \u203A Rules",keywords:"style rules styleRules metric status color scale pulse",where:ue("rules")},{label:"Assets",hint:"Left panel",keywords:"models placements grid composition",where:{panel:"left",tab:"assets"}},{label:"Annotations",hint:"Left panel",keywords:"hotspots markers notes",where:{panel:"left",tab:"annotations"}},{label:"Measurements",hint:"Left panel",keywords:"distance area calibrate units",where:{panel:"left",tab:"measure"}},{label:"Sequences",hint:"Timeline",keywords:"keyframes tracks timeline",where:{panel:"dock",tab:"sequences"}},{label:"Clips",hint:"Timeline",keywords:"animations autoplay loop speed",where:{panel:"dock",tab:"clips"}},{label:"Cinematic",hint:"Timeline",keywords:"waypoints camera path",where:{panel:"dock",tab:"cinematic"}}];function bp(e){requestAnimationFrame(()=>{let t=document.querySelector(`.bb-root [data-ri-section="${CSS.escape(e)}"]`);if(!t)return;let i=t.querySelector('button[aria-expanded="false"]');i?.closest("[data-ri-section]")===t&&i.click(),t.scrollIntoView({block:"nearest"}),t.classList.add("bb-flash"),window.setTimeout(()=>t.classList.remove("bb-flash"),900)})}import{useEffect as Zf,useRef as Qf,useState as br}from"react";import{Lock as eh,Plus as th,Trash2 as oh}from"lucide-react";import{RotateCcw as Gf}from"lucide-react";import{jsx as ai}from"react/jsx-runtime";function ut({panelKey:e,title:t,tooltip:i,toggleLabel:a,controls:o,children:n,requiredTier:d,core:s=!1}){let{openMaterialPanels:p,materialPanelEnabled:c,onToggleMaterialPanel:x,onSetMaterialPanelState:h}=o,g=d?.locked??!1;return o.visibleLayers.has(e)?ai(Uc,{title:t,tooltip:i,disabled:g||!s&&!c[e],open:p[e],onToggle:()=>x(e),trailing:s?ai("button",{type:"button",className:"se-iconButton",title:`Clear ${t.toLowerCase()} overrides`,"aria-label":`Clear ${t.toLowerCase()} overrides`,onClick:()=>h(e,!1),children:ai(Gf,{size:12})}):ai(se,{checked:!g&&c[e],onChange:g?()=>{}:C=>h(e,C),label:a??`Toggle ${t}`}),children:g&&d?ai(We,{requiredTier:d.tier,feature:t}):n}):null}import{createContext as qf,useContext as Wf,useRef as Yf}from"react";import{FileUp as Jf}from"lucide-react";import{jsx as Ie,jsxs as Mo}from"react/jsx-runtime";var La=qf(null);function Fe({label:e,value:t,placeholder:i,onChange:a,path:o}){let n=Yf(null),d=Wf(La);return Mo("div",{className:"bb-field bb-field--row","data-ri-path":o,children:[Ie("label",{className:"bb-label",title:e,children:e}),Mo("div",{className:"bb-fileField",title:d??void 0,children:[Ie("input",{className:"bb-input bb-fileField-input",placeholder:i,value:t,disabled:!!d&&!t,onChange:s=>{let p=s.target.value;!p&&t&&qn(t),a(p)}}),Ie("button",{type:"button",className:"bb-fileFieldButton",disabled:!!d,onClick:()=>n.current?.click(),"aria-label":`Select file for ${e}`,title:`Select file for ${e}`,children:Ie(Jf,{size:13})}),Ie("input",{ref:n,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif",className:"bb-hiddenInput",onChange:s=>{let p=s.target.files?.[0];if(!p)return;let c=gn(p);t&&t!==c&&qn(t),It(c,URL.createObjectURL(p)),a(c),s.target.value=""}})]})]})}function Po({label:e,value:t,fallback:i="#ffffff",onChange:a,path:o}){return Mo("div",{className:"bb-field bb-field--row","data-ri-path":o,children:[Ie("span",{className:"bb-label",children:e}),Ie(Rd,{label:e,value:t||i,onChange:a})]})}function si({label:e,checked:t,onChange:i,path:a}){return Mo("label",{className:"bb-field bb-field--row","data-ri-path":a,children:[Ie("span",{className:"bb-label",title:e,children:e}),Ie("span",{className:"rui-checkCell",children:Ie("input",{type:"checkbox",checked:t,onChange:o=>i(o.target.checked)})})]})}function gp({label:e,value:t,min:i,max:a,step:o,placeholder:n,disabled:d,onChange:s,path:p}){return Mo("div",{className:"bb-field bb-field--row","data-ri-path":p,children:[Ie("label",{className:"bb-label",title:e,children:e}),Ie("input",{className:"bb-input",type:"number",min:i,max:a,step:o,placeholder:n,disabled:d,value:t??"",onChange:c=>s(c.target.value===""?void 0:Number(c.target.value))})]})}function Xf(e,t){let i=t<1?Math.ceil(-Math.log10(t)):0,a=10**Math.max(i,0);return Math.round(e*a)/a}function Da({label:e,value:t,min:i,max:a,step:o=.01,disabled:n,onChange:d,path:s}){let p=t??0,c=h=>{let g=h;return i!==void 0&&(g=Math.max(i,g)),a!==void 0&&(g=Math.min(a,g)),g},x=Bd({value:p,step:o,min:i,max:a,disabled:n,onChange:h=>d(Xf(h,o))});return Mo("div",{className:"bb-field bb-field--row","data-ri-path":s,children:[Ie("label",{className:"bb-label bb-label--scrub",title:"Drag to change",...x,children:e}),Ie("input",{className:"bb-input",type:"number",min:i,max:a,step:o,disabled:n,value:p,onChange:h=>{h.target.value!==""&&d(c(Number(h.target.value)))}})]})}function Tn({label:e,value:t,options:i,onChange:a,path:o}){return Mo("div",{className:"bb-field bb-field--row","data-ri-path":o,children:[Ie("label",{className:"bb-label",title:e,children:e}),i.length<=3?Ie("div",{className:"se-segmentedControl",children:i.map(n=>Ie("button",{type:"button",className:`se-segmentedOption ${n===t?"se-segmentedOption--active":""}`,onClick:()=>a(n),children:n.charAt(0).toUpperCase()+n.slice(1)},n))}):Ie("select",{className:"bb-select",value:t,onChange:n=>a(n.target.value),children:i.map(n=>Ie("option",{value:n,children:n.charAt(0).toUpperCase()+n.slice(1)},n))})]})}function ye({label:e,value:t,min:i,max:a,step:o,onChange:n,path:d}){return Mo("div",{className:"bb-field bb-field--row","data-ri-path":d,children:[Ie("span",{className:"bb-label",children:e}),Ie(Td,{label:e,value:t??i,unset:t===void 0,min:i,max:a,step:o,onChange:n})]})}import{Fragment as hp,jsx as z,jsxs as Ae}from"react/jsx-runtime";var mp="This object has no texture coordinates (UVs), so image maps can't be placed on it. Colors and the other settings work, and Decals can put an image on it.",fp=[{key:"pbr",label:"Surface",core:!0},{key:"roughness",label:"Roughness",core:!0},{key:"opacity",label:"Opacity",core:!0},{key:"normalBump",label:"Normal and bump"},{key:"emission",label:"Emission"},{key:"ao",label:"Ambient occlusion"},{key:"faces",label:"Faces"},{key:"displacement",label:"Displacement",advanced:!0},{key:"clearcoat",label:"Clearcoat",advanced:!0},{key:"sheen",label:"Sheen",advanced:!0},{key:"anisotropy",label:"Anisotropy",advanced:!0},{key:"transmission",label:"Transmission and volume",advanced:!0}];function xp({selectedItem:e,selectedMaterial:t,pbrWorkflow:i,onPbrWorkflowChange:a,openMaterialPanels:o,materialPanelEnabled:n,onToggleMaterialPanel:d,onSetMaterialPanelState:s,updateSelectedMaterial:p,setSelectedTexturePath:c,isTexturePositioningEnabled:x,onConfirmTexturePosition:h,takesImage:g=!0}){let{tier:C}=it(),M={tier:"starter",locked:!nt(C,"advancedMaterials")},[y,T]=br(()=>new Set),[f,u]=br(!1),v=Qf(null);hn([v],()=>u(!1),f),Zf(()=>T(new Set),[e]);let m=new Set(fp.filter(w=>w.core||n[w.key]||y.has(w.key)).map(w=>w.key)),N=fp.filter(w=>!m.has(w.key)),A=w=>{u(!1),T(I=>new Set(I).add(w)),s(w,!0),o[w]||d(w)},G={openMaterialPanels:o,materialPanelEnabled:n,onToggleMaterialPanel:d,onSetMaterialPanelState:s,visibleLayers:m},[B,P]=br("roughness"),[$,H]=br("factor"),de=(w,I)=>{p(e,he=>{if(!he?.texture?.path)return he??{};let Ne=he.texture.offset??[0,0],j=[Ne[0],Ne[1]];return j[w]=I,{...he,texture:{...he.texture,offset:j}}})},_=w=>{p(e,I=>{if(!I?.texture?.path)return I??{};let he=(w%360+360)%360;return{...I,texture:{...I.texture,rotation:he*Math.PI/180}}})},Q=()=>{c(e,"texture","")};return Ae(La.Provider,{value:g?null:mp,children:[g?null:z("p",{className:"bb-note bb-materialNotice",children:mp}),z(ut,{panelKey:"pbr",core:!0,title:"Surface",tooltip:"Controls the base color and workflow used for physically based shading.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Tn,{label:"Workflow",value:i,options:["metalness","specular"],onChange:a}),z(Fe,{path:"objectBindings[\u2026].style.material.texture.path",label:i==="specular"?"Albedo map":"Base map",placeholder:"materials/oak-wood.jpg",value:t?.texture?.path??"",onChange:w=>c(e,"texture",w)}),t?.texture?.path?Ae("div",{className:"rui-group",children:[Ae("div",{className:"rui-groupHeader",children:[z("span",{children:"Texture position"}),z("button",{type:"button",className:"se-iconButton",onClick:Q,title:"Remove the texture and its position","aria-label":"Remove the texture and its position",children:z(oh,{size:13})})]}),Ae("div",{className:"bb-grid",children:[z(Da,{path:"objectBindings[\u2026].style.material.texture.offset",label:"Offset X",value:t?.texture?.offset?.[0]??0,step:.01,onChange:w=>de(0,w)}),z(Da,{path:"objectBindings[\u2026].style.material.texture.offset",label:"Offset Y",value:t?.texture?.offset?.[1]??0,step:.01,onChange:w=>de(1,w)})]}),z(ye,{label:"Rotation",value:((t?.texture?.rotation??0)*180/Math.PI%360+360)%360,min:0,max:360,step:1,onChange:w=>_(w??0)}),x?z("button",{type:"button",className:"bb-button rui-inlineButton",onClick:h,title:"Confirm this texture position and exit positioning mode",children:"Done positioning"}):z("p",{className:"bb-note",style:{margin:"6px 0 0"},children:"Double-click the object in the preview to drag its texture directly (scroll to zoom), or edit its offset numerically once positioning."})]}):null,z(Po,{path:"objectBindings[\u2026].style.material.baseColor",label:i==="specular"?"Albedo color":"Base color",value:t?.baseColor??"#ffffff",onChange:w=>p(e,I=>({...I,baseColor:w}))}),i==="metalness"?Ae(hp,{children:[z(ye,{path:"objectBindings[\u2026].style.material.metalness",label:"Metalness",value:t?.metalness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,metalness:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.metalnessMap.path",label:"Metalness map",placeholder:"materials/body-metalness.jpg",value:t?.metalnessMap?.path??"",onChange:w=>c(e,"metalnessMap",w)})]}):Ae(hp,{children:[z(ye,{path:"objectBindings[\u2026].style.material.specularIntensity",label:"Specular intensity",value:t?.specularIntensity,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,specularIntensity:w}))}),z(Po,{path:"objectBindings[\u2026].style.material.specularColor",label:"Specular color",value:t?.specularColor??"#ffffff",onChange:w=>p(e,I=>({...I,specularColor:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.specularIntensityMap.path",label:"Intensity map",placeholder:"materials/body-specular-intensity.jpg",value:t?.specularIntensityMap?.path??"",onChange:w=>c(e,"specularIntensityMap",w)}),z(Fe,{path:"objectBindings[\u2026].style.material.specularColorMap.path",label:"Color map",placeholder:"materials/body-specular-color.jpg",value:t?.specularColorMap?.path??"",onChange:w=>c(e,"specularColorMap",w)})]}),z(ye,{path:"objectBindings[\u2026].style.material.reflectivity",label:"Reflectivity",value:t?.reflectivity,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,reflectivity:w}))})]})}),z(ut,{panelKey:"roughness",core:!0,title:"Roughness",tooltip:"Adjusts how matte or shiny the surface appears.",toggleLabel:"Toggle Roughness and Glossiness",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Tn,{label:"Mode",value:B,options:["roughness","glossiness"],onChange:P}),z("div",{className:"bb-field bb-field--full",children:z("p",{className:"bb-note",children:B==="roughness"?"Roughness: 0 is glossy, 1 is matte.":"Glossiness is the inverse of roughness (glossiness = 1 \u2212 roughness)"})}),B==="roughness"?z(ye,{path:"objectBindings[\u2026].style.material.roughness",label:"Roughness",value:t?.roughness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,roughness:w}))}):z(ye,{path:"objectBindings[\u2026].style.material.roughness",label:"Glossiness",value:t?.roughness===void 0?void 0:1-t.roughness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,roughness:w===void 0?void 0:1-w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.roughnessMap.path",label:B==="glossiness"?"Glossiness map":"Roughness map",placeholder:"materials/body-roughness.jpg",value:t?.roughnessMap?.path??"",onChange:w=>c(e,"roughnessMap",w)})]})}),z(ut,{panelKey:"emission",title:"Emission",tooltip:"Makes the material self-illuminated with emissive color and intensity.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Po,{path:"objectBindings[\u2026].style.material.emissive",label:"Color",value:t?.emissive??"#000000",fallback:"#000000",onChange:w=>p(e,I=>({...I,emissive:w}))}),z(ye,{path:"objectBindings[\u2026].style.material.emissiveIntensity",label:"Intensity",value:t?.emissiveIntensity,min:0,max:10,step:.1,onChange:w=>p(e,I=>({...I,emissiveIntensity:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.emissiveMap.path",label:"Map",placeholder:"materials/body-emissive.jpg",value:t?.emissiveMap?.path??"",onChange:w=>c(e,"emissiveMap",w)})]})}),z(ut,{panelKey:"opacity",core:!0,title:"Opacity",tooltip:"Controls transparency, alpha testing, and blending behavior.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(ye,{path:"objectBindings[\u2026].style.material.opacity",label:"Opacity",value:t?.opacity,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,opacity:w}))}),z(ye,{path:"objectBindings[\u2026].style.material.alphaTest",label:"Alpha test",value:t?.alphaTest,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,alphaTest:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.alphaMap.path",label:"Alpha map",placeholder:"materials/body-alpha.png",value:t?.alphaMap?.path??"",onChange:w=>c(e,"alphaMap",w)}),z(Tn,{path:"objectBindings[\u2026].style.material.blendingMode",label:"Blending mode",value:t?.blendingMode??"normal",options:wd,onChange:w=>p(e,I=>({...I,blendingMode:w}))}),z(si,{path:"objectBindings[\u2026].style.material.alphaHash",label:"Alpha hash",checked:t?.alphaHash??!1,onChange:w=>p(e,I=>({...I,alphaHash:w}))}),z(si,{path:"objectBindings[\u2026].style.material.dithering",label:"Dithering",checked:t?.dithering??!1,onChange:w=>p(e,I=>({...I,dithering:w}))})]})}),Ae(ut,{panelKey:"normalBump",title:"Normal and bump",tooltip:"Adds surface detail without changing the actual mesh shape.",toggleLabel:"Toggle Normal and Bump",controls:G,children:[Ae("div",{className:"bb-grid",children:[z(Fe,{path:"objectBindings[\u2026].style.material.normalMap.path",label:"Normal map",placeholder:"materials/body-normal.jpg",value:t?.normalMap?.path??"",onChange:w=>c(e,"normalMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.normalScale",label:"Normal scale",value:t?.normalScale,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,normalScale:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.bumpMap.path",label:"Bump map",placeholder:"materials/body-bump.jpg",value:t?.bumpMap?.path??"",onChange:w=>c(e,"bumpMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.bumpScale",label:"Bump scale",value:t?.bumpScale,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,bumpScale:w}))})]}),z(si,{path:"objectBindings[\u2026].style.material.flipNormalY",label:"Flip normal Y",checked:t?.flipNormalY??!1,onChange:w=>p(e,I=>({...I,flipNormalY:w}))})]}),z(ut,{panelKey:"displacement",requiredTier:M,title:"Displacement",tooltip:"Offsets geometry using a texture to create real surface height.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Fe,{path:"objectBindings[\u2026].style.material.displacementMap.path",label:"Map",placeholder:"materials/body-displacement.jpg",value:t?.displacementMap?.path??"",onChange:w=>c(e,"displacementMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.displacementScale",label:"Scale",value:t?.displacementScale,min:-5,max:5,step:.01,onChange:w=>p(e,I=>({...I,displacementScale:w}))}),z(ye,{path:"objectBindings[\u2026].style.material.displacementBias",label:"Bias",value:t?.displacementBias,min:-5,max:5,step:.01,onChange:w=>p(e,I=>({...I,displacementBias:w}))})]})}),z(ut,{panelKey:"ao",title:"Ambient occlusion",tooltip:"Darkens creases and contact areas to add depth.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(Fe,{path:"objectBindings[\u2026].style.material.aoMap.path",label:"Map",placeholder:"materials/body-ao.jpg",value:t?.aoMap?.path??"",onChange:w=>c(e,"aoMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.aoMapIntensity",label:"Intensity",value:t?.aoMapIntensity,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,aoMapIntensity:w}))})]})}),Ae(ut,{panelKey:"clearcoat",requiredTier:M,title:"Clearcoat",tooltip:"Adds a glossy protective layer on top of the base material.",controls:G,children:[Ae("div",{className:"bb-grid",children:[z(Fe,{path:"objectBindings[\u2026].style.material.clearcoatMap.path",label:"Coat map",placeholder:"materials/body-clearcoat.jpg",value:t?.clearcoatMap?.path??"",onChange:w=>c(e,"clearcoatMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.clearcoat",label:"Clearcoat",value:t?.clearcoat,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,clearcoat:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.clearcoatRoughnessMap.path",label:"Roughness map",placeholder:"materials/body-clearcoat-roughness.jpg",value:t?.clearcoatRoughnessMap?.path??"",onChange:w=>c(e,"clearcoatRoughnessMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.clearcoatRoughness",label:"Roughness",value:t?.clearcoatRoughness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,clearcoatRoughness:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.clearcoatNormalMap.path",label:"Normal map",placeholder:"materials/body-clearcoat-normal.jpg",value:t?.clearcoatNormalMap?.path??"",onChange:w=>c(e,"clearcoatNormalMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.clearcoatNormalScale",label:"Normal scale",value:t?.clearcoatNormalScale,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,clearcoatNormalScale:w}))})]}),z(si,{path:"objectBindings[\u2026].style.material.flipClearcoatNormalY",label:"Flip normal Y",checked:t?.flipClearcoatNormalY??!1,onChange:w=>p(e,I=>({...I,flipClearcoatNormalY:w}))})]}),z(ut,{panelKey:"sheen",requiredTier:M,title:"Sheen",tooltip:"Adds a soft fabric-like sheen on grazing angles.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(ye,{path:"objectBindings[\u2026].style.material.sheen",label:"Sheen",value:t?.sheen,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,sheen:w}))}),z(Po,{path:"objectBindings[\u2026].style.material.sheenColor",label:"Color",value:t?.sheenColor??"#ffffff",onChange:w=>p(e,I=>({...I,sheenColor:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.sheenColorMap.path",label:"Color map",placeholder:"materials/body-sheen-color.jpg",value:t?.sheenColorMap?.path??"",onChange:w=>c(e,"sheenColorMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.sheenRoughness",label:"Roughness",value:t?.sheenRoughness,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,sheenRoughness:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.sheenRoughnessMap.path",label:"Roughness map",placeholder:"materials/body-sheen-roughness.jpg",value:t?.sheenRoughnessMap?.path??"",onChange:w=>c(e,"sheenRoughnessMap",w)})]})}),z(ut,{panelKey:"anisotropy",requiredTier:M,title:"Anisotropy",tooltip:"Stretches reflections in one direction for brushed or fiber-like surfaces.",controls:G,children:Ae("div",{className:"bb-grid",children:[z(ye,{path:"objectBindings[\u2026].style.material.anisotropy",label:"Intensity",value:t?.anisotropy,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,anisotropy:w}))}),z(Tn,{label:"Direction",value:$,options:["factor","texture"],onChange:H}),$==="factor"?z(ye,{path:"objectBindings[\u2026].style.material.anisotropyRotation",label:"Rotation",value:t?.anisotropyRotation,min:0,max:6.28,step:.01,onChange:w=>p(e,I=>({...I,anisotropyRotation:w}))}):z(Fe,{path:"objectBindings[\u2026].style.material.anisotropyMap.path",label:"Map",placeholder:"materials/body-anisotropy.jpg",value:t?.anisotropyMap?.path??"",onChange:w=>c(e,"anisotropyMap",w)})]})}),z(ut,{panelKey:"transmission",requiredTier:M,title:"Transmission and volume",tooltip:"Controls glass-like transmission and how light travels through volume.",toggleLabel:"Toggle Transmission and Volume",controls:G,children:Ae("div",{className:"bb-grid",children:[z(ye,{path:"objectBindings[\u2026].style.material.transmission",label:"Transmission",value:t?.transmission,min:0,max:1,step:.01,onChange:w=>p(e,I=>({...I,transmission:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.transmissionMap.path",label:"Map",placeholder:"materials/body-transmission.jpg",value:t?.transmissionMap?.path??"",onChange:w=>c(e,"transmissionMap",w)}),z(ye,{path:"objectBindings[\u2026].style.material.thickness",label:"Thickness",value:t?.thickness,min:0,max:5,step:.01,onChange:w=>p(e,I=>({...I,thickness:w}))}),z(Fe,{path:"objectBindings[\u2026].style.material.thicknessMap.path",label:"Thickness map",placeholder:"materials/body-thickness.jpg",value:t?.thicknessMap?.path??"",onChange:w=>c(e,"thicknessMap",w)}),z(Po,{path:"objectBindings[\u2026].style.material.attenuationColor",label:"Volume tint",value:t?.attenuationColor??"#ffffff",onChange:w=>p(e,I=>({...I,attenuationColor:w}))}),z(gp,{path:"objectBindings[\u2026].style.material.attenuationDistance",label:"Attenuation",value:t?.attenuationDistance,min:0,step:.01,placeholder:"Infinity when unset",onChange:w=>p(e,I=>({...I,attenuationDistance:w}))})]})}),z(ut,{panelKey:"faces",title:"Faces",tooltip:"Chooses which side of the mesh renders and how backfaces are handled.",controls:G,children:z("div",{className:"bb-grid",children:z(Tn,{path:"objectBindings[\u2026].style.material.side",label:"Side",value:t?.side??"front",options:yd,onChange:w=>p(e,I=>({...I,side:w}))})})}),N.length?Ae("div",{className:"se-listHeader se-listHeader--footer",ref:v,children:[Ae("button",{type:"button",className:"bb-button bb-button--ghost bb-button--small","aria-expanded":f,onClick:()=>u(w=>!w),children:[z(th,{size:13,"aria-hidden":"true"}),"Add layer"]}),f?z("div",{className:"se-addMenu se-addMenu--up",role:"menu","aria-label":"Add layer",children:N.map(w=>Ae("button",{type:"button",role:"menuitem",onClick:()=>A(w.key),children:[z("span",{children:w.label}),w.advanced&&M.locked?z(eh,{size:12,"aria-label":"Needs an upgrade"}):null]},w.key))}):null]}):null]})}import{useRef as rh,useState as ah}from"react";import{Ban as sh,ChevronDown as lh}from"lucide-react";var gr="default",Fa=[{id:gr,label:"Default",swatch:"transparent",material:{}},{id:"wood",label:"Wood",swatch:"#8b5a2b",material:{baseColor:"#8b5a2b",metalness:0,roughness:.75,reflectivity:.04}},{id:"brushed-metal",label:"Brushed Metal",swatch:"linear-gradient(135deg, #cfcfcf, #8a8a8a)",material:{baseColor:"#c8c8c8",metalness:1,roughness:.35}},{id:"chrome",label:"Polished Chrome",swatch:"linear-gradient(135deg, #ffffff, #9aa0a6)",material:{baseColor:"#e8e8e8",metalness:1,roughness:.05}},{id:"gold",label:"Gold",swatch:"linear-gradient(135deg, #ffe9a8, #c89b2c)",material:{baseColor:"#e6b325",metalness:1,roughness:.2}},{id:"copper",label:"Copper",swatch:"linear-gradient(135deg, #e3a576, #8a4a26)",material:{baseColor:"#b87333",metalness:1,roughness:.3}},{id:"glass",label:"Glass",swatch:"linear-gradient(135deg, rgba(255,255,255,0.9), rgba(180,210,230,0.4))",material:{baseColor:"#ffffff",metalness:0,roughness:.02,reflectivity:.5,opacity:1,transmission:1,thickness:.5,attenuationColor:"#ffffff",attenuationDistance:1}},{id:"frosted-glass",label:"Frosted Glass",swatch:"linear-gradient(135deg, rgba(255,255,255,0.85), rgba(210,225,235,0.6))",material:{baseColor:"#ffffff",metalness:0,roughness:.4,reflectivity:.3,opacity:1,transmission:.9,thickness:.5}},{id:"plastic-glossy",label:"Glossy Plastic",swatch:"#dadada",material:{baseColor:"#dadada",metalness:0,roughness:.25,reflectivity:.5,clearcoat:.3,clearcoatRoughness:.1}},{id:"plastic-matte",label:"Matte Plastic",swatch:"#9a9a9a",material:{baseColor:"#9a9a9a",metalness:0,roughness:.85,reflectivity:.04}},{id:"rubber",label:"Rubber",swatch:"#1a1a1a",material:{baseColor:"#1a1a1a",metalness:0,roughness:.9,reflectivity:.02}},{id:"fabric",label:"Fabric",swatch:"#9c8a6b",material:{baseColor:"#9c8a6b",metalness:0,roughness:.95,sheen:.4,sheenColor:"#ffffff",sheenRoughness:.6}},{id:"ceramic",label:"Ceramic",swatch:"#f5f5f0",material:{baseColor:"#f5f5f0",metalness:0,roughness:.15,clearcoat:.6,clearcoatRoughness:.1}},{id:"concrete",label:"Concrete",swatch:"#9b9b93",material:{baseColor:"#9b9b93",metalness:0,roughness:.95,reflectivity:.03}}],nh=Array.from(new Set(Fa.flatMap(e=>Object.keys(e.material)))),ih=Object.fromEntries(nh.map(e=>[e,void 0]));function vp(e){return e.id===gr?ih:e.material}import{jsx as Wo,jsxs as Ha}from"react/jsx-runtime";function yp({disabled:e,onApply:t}){let[i,a]=ah(!1),o=rh(null);return hn([o],()=>a(!1),i),Ha("div",{className:"se-field se-fieldInline bb-presetRow",ref:o,children:[Wo("span",{className:"se-fieldLabel",children:"Preset"}),Ha("button",{type:"button",className:"bb-presetButton",disabled:e,"aria-expanded":i,onClick:()=>a(n=>!n),children:[Wo("span",{children:"Apply a preset"}),Wo(lh,{size:12,"aria-hidden":"true"})]}),i?Wo("div",{className:"se-addMenu bb-presetMenu",role:"menu","aria-label":"Material presets",children:Fa.map(n=>Ha("button",{type:"button",role:"menuitem",onClick:()=>{a(!1),t(vp(n))},children:[Wo("span",{className:"bb-presetSwatch",style:{background:n.swatch},children:n.id===gr?Wo(sh,{size:10,"aria-hidden":"true"}):null}),Wo("span",{className:"bb-presetLabel",children:n.label})]},n.id))}):null]})}import{jsx as Rn,jsxs as $a}from"react/jsx-runtime";function wp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o,idError:n}){return Rn(Ye,{title:"Identity",open:i,onToggle:a,children:$a("div",{className:"bb-grid",children:[$a("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].modelObjectId",children:[Rn("label",{className:"bb-label",title:"The object's exact name in the model file. It can't be changed.",children:"Model object ID"}),Rn("input",{className:"bb-input bb-readonly",value:t.modelObjectId,readOnly:!0})]}),$a("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].id",children:[Rn("label",{className:"bb-label",children:"ID"}),Rn("input",{className:`bb-input ${n?"bb-input--error":""}`,value:t.id,onChange:d=>o(e,s=>({...s,id:d.target.value}))}),n?Rn("span",{className:"bb-status bb-status--error bb-fieldFull",children:n}):null]})]})})}import{useEffect as dh,useState as Sp}from"react";import{jsx as Ze,jsxs as Dt}from"react/jsx-runtime";function kp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o}){let[n,d]=Sp(t.group??""),[s,p]=Sp(t.tags?.join(", ")??"");dh(()=>{d(t.group??""),p(t.tags?.join(", ")??"")},[e,t.group,t.tags]);let c=()=>{o(e,h=>({...h,group:n.trim()||void 0}))},x=()=>{let h=[...new Set(s.split(",").map(g=>g.trim()).filter(Boolean))];o(e,g=>({...g,tags:h.length>0?h:void 0}))};return Dt(Ye,{title:"Basics",open:i,onToggle:a,children:[Dt("div",{className:"bb-grid",children:[Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Label"}),Ze("input",{className:"bb-input",value:t.label??"",onChange:h=>o(e,g=>({...g,label:h.target.value}))})]}),Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Type"}),Ze("input",{className:"bb-input",list:"binding-type-suggestions",value:t.type??"other",onChange:h=>o(e,g=>({...g,type:h.target.value}))}),Ze("datalist",{id:"binding-type-suggestions",children:Nd.map(h=>Ze("option",{value:h},h))})]}),Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Status"}),Ze("select",{className:"bb-select",value:t.status??"normal",onChange:h=>o(e,g=>({...g,status:h.target.value})),children:Ad.map(h=>Ze("option",{value:h,children:h},h))})]}),Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Group"}),Ze("input",{className:"bb-input",placeholder:"paint",value:n,onChange:h=>d(h.target.value),onBlur:c,onKeyDown:h=>{h.key==="Enter"&&h.currentTarget.blur()}})]}),Dt("div",{className:"bb-field",children:[Ze("label",{className:"bb-label",children:"Tags"}),Ze("input",{className:"bb-input",placeholder:"exterior, configurable",value:s,onChange:h=>p(h.target.value),onBlur:x,onKeyDown:h=>{h.key==="Enter"&&h.currentTarget.blur()}})]})]}),Dt("div",{className:"bb-checkboxRow",children:[Dt("label",{className:"bb-checkbox",children:[Ze("input",{type:"checkbox",checked:t.selectable!==!1,onChange:h=>o(e,g=>({...g,selectable:h.target.checked}))}),"Selectable"]}),Dt("label",{className:"bb-checkbox",children:[Ze("input",{type:"checkbox",checked:t.hoverable!==!1,onChange:h=>o(e,g=>({...g,hoverable:h.target.checked}))}),"Hoverable"]}),Dt("label",{className:"bb-checkbox",children:[Ze("input",{type:"checkbox",checked:t.visible!==!1,onChange:h=>o(e,g=>({...g,visible:h.target.checked}))}),"Visible"]})]})]})}import{useEffect as ch,useState as ph}from"react";import{Plus as uh,Trash2 as bh}from"lucide-react";import{Fragment as mh,jsx as He,jsxs as bt}from"react/jsx-runtime";var Cp=da.filter(e=>e.handling==="viewer"),gh=da.filter(e=>e.handling==="host");function Mp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o,takesImage:n=!0}){let[d,s]=ph(new Set);ch(()=>{s(new Set)},[e]);let p=t.actions??[],c=(g,C)=>o(e,M=>({...M,actions:(M.actions??[]).map((y,T)=>T===g?C(y):y)})),x=g=>{o(e,C=>({...C,actions:(C.actions??[]).filter((M,y)=>y!==g)})),s(C=>{let M=new Set;return C.forEach(y=>{y<g?M.add(y):y>g&&M.add(y-1)}),M})},h=(g,C)=>s(M=>{let y=new Set(M);return C?y.add(g):y.delete(g),y});return bt(Ye,{title:"Actions",open:i,onToggle:a,children:[He("div",{className:"bb-actionList",children:p.map((g,C)=>{let M=Yi(g.id),y=d.has(C)||!M,T=g.id.trim(),f=M?null:Yl(g.id),u=T.length>0&&p.some((v,m)=>m!==C&&v.id.trim()===T);return bt("div",{className:"bb-actionCard",children:[bt("div",{className:"rui-groupHeader",children:[bt("span",{children:["Action ",C+1]}),He("button",{type:"button",className:"se-iconButton",title:"Remove action","aria-label":`Remove action ${C+1}`,onClick:()=>x(C),children:He(bh,{size:13})})]}),bt("div",{className:"bb-actionGrid",children:[bt("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].actions[\u2026].id",children:[He("label",{className:"bb-label",children:"ID"}),bt("select",{className:"bb-select",value:y?Wi:g.id,onChange:v=>{let m=v.target.value;if(m===Wi){h(C,!0);return}h(C,!1);let N=Yi(m);c(C,A=>({...A,id:m,label:N&&ca(A.label)?N.label:A.label}))},children:[He("optgroup",{label:"Handled by the viewer",children:Cp.map(v=>He("option",{value:v.id,children:v.id},v.id))}),He("optgroup",{label:"Handled by your app",children:gh.map(v=>He("option",{value:v.id,children:v.id},v.id))}),He("option",{value:Wi,children:"Custom\u2026"})]})]}),y?bt("div",{className:"bb-field bb-field--row",children:[He("label",{className:"bb-label",children:"Custom ID"}),He("input",{className:"bb-input",value:g.id,placeholder:"open-datasheet",onChange:v=>{h(C,!0),c(C,m=>({...m,id:v.target.value}))}})]}):null,bt("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].actions[\u2026].label",children:[He("label",{className:"bb-label",children:"Label"}),He("input",{className:"bb-input",value:g.label,onChange:v=>c(C,m=>({...m,label:v.target.value}))})]}),M?.id==="change-material"&&!n?He("span",{className:"bb-note bb-note--warning",children:"This object has no texture coordinates, so an image picked here can't be placed on it, and the viewer says so. Change Color and Add Image work."}):M?He("span",{className:"bb-note",children:M.description}):T.length===0?He("span",{className:"bb-note bb-note--error",children:"An action ID is required, the button renders but can never be identified in onAction."}):bt("span",{className:"bb-note bb-note--warning",children:["Unrecognised ID, the viewer has no built-in behavior for it. Add declarative effects and execute them with useViewerActions, or handle it in onAction.",f?bt(mh,{children:[" Did you mean ",He("button",{type:"button",className:"bb-linkButton",onClick:()=>{h(C,!1);let v=Yi(f);c(C,m=>({...m,id:f,label:v&&ca(m.label)?v.label:m.label}))},children:f}),"?"]}):null]}),g.effects?.length?bt("span",{className:"bb-note",children:[g.effects.length," declarative effect",g.effects.length===1?"":"s",", execute with useViewerActions."]}):null,u?He("span",{className:"bb-note bb-note--warning",children:"Another action on this binding uses the same ID, they will render as two identical buttons."}):null]})]},C)})}),He(to,{children:bt("button",{type:"button",className:"bb-button",onClick:()=>{let g=Cp.find(C=>!p.some(M=>M.id===C.id));o(e,C=>({...C,actions:[...C.actions??[],{id:g?.id??"",label:g?.label??"New action",type:"command"}]})),g||h(p.length,!0)},children:[He(uh,{size:13,"aria-hidden":"true"}),"Add action"]})})]})}import{useRef as fh}from"react";import{Image as hh,ImagePlus as xh,Trash2 as vh,Type as Pp}from"lucide-react";import{Fragment as Tp,jsx as Ke,jsxs as gt}from"react/jsx-runtime";var Bp=()=>`decal-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;function Rp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o,placement:n,onPlacementChange:d,defaultSize:s,onImageFile:p,onNudge:c}){let{tier:x}=it(),h=fh(null),g=t.decals??[],C=n?.nodeKey===e?n:null,M=f=>o(e,u=>({...u,decals:f.length>0?f:void 0})),y=(f,u)=>M(g.map(v=>v.id===f?{...v,...u}:v)),T=f=>{f.image&&qn(f.image),C?.decal.id===f.id&&d(null),M(g.filter(u=>u.id!==f.id))};return gt(Ye,{title:"Decals",open:i,onToggle:a,tooltip:"Print a logo, image, or text on the selected object's surface.",children:[St(x,"decalsPerObject",g.length)?null:Ke(We,{requiredTier:Ho("decalsPerObject",g.length),feature:"More decals on this object"}),gt(Tp,{children:[gt("div",{className:"rui-actions",children:[gt("button",{type:"button",className:"bb-button",disabled:!St(x,"decalsPerObject",g.length),onClick:()=>h.current?.click(),children:[Ke(xh,{size:13,"aria-hidden":"true"})," Add image"]}),gt("button",{type:"button",className:"bb-button",disabled:!St(x,"decalsPerObject",g.length),onClick:()=>d({nodeKey:e,decal:{id:Bp(),text:"Your text",color:"#ffffff",size:s}}),children:[Ke(Pp,{size:13,"aria-hidden":"true"})," Add text"]}),Ke("input",{ref:h,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif,image/svg+xml",className:"bb-hiddenInput",onChange:f=>{let u=f.target.files?.[0];if(f.target.value="",!u)return;let v=gn(u);It(v,URL.createObjectURL(u)),p?.(v,u),d({nodeKey:e,decal:{id:Bp(),image:v,size:s}})}})]}),g.length===0&&!C?Ke("p",{className:"se-listEmpty",children:"No decals on this object yet."}):null,g.map(f=>gt("div",{className:"bb-decalCard",children:[gt("div",{className:"rui-groupHeader",children:[gt("span",{className:"rui-groupTitle",title:f.image??f.text,children:[f.image?Ke(hh,{size:13,"aria-hidden":"true"}):Ke(Pp,{size:13,"aria-hidden":"true"}),f.image??f.text]}),Ke("button",{type:"button",className:"se-iconButton",title:"Delete decal","aria-label":"Delete decal",onClick:()=>T(f),children:Ke(vh,{size:13})})]}),Ke(Jl,{onNudge:u=>c(f.id,u)}),gt("div",{className:"bb-grid",children:[f.image?null:gt(Tp,{children:[gt("div",{className:"bb-field bb-field--row",children:[Ke("label",{className:"bb-label",children:"Text"}),Ke("input",{className:"bb-input",value:f.text??"",onChange:u=>y(f.id,{text:u.target.value})})]}),Ke(Po,{label:"Color",variant:"input",value:f.color??"#ffffff",onChange:u=>y(f.id,{color:u})}),gt("div",{className:"bb-field bb-field--row",children:[Ke("label",{className:"bb-label",children:"Weight"}),gt("select",{className:"bb-select",value:f.fontWeight??"bold",onChange:u=>y(f.id,{fontWeight:u.target.value}),children:[Ke("option",{value:"bold",children:"Bold"}),Ke("option",{value:"normal",children:"Regular"})]})]})]}),Ke(ye,{label:"Size",value:Number(f.size.toFixed(4)),min:Number((s/20).toPrecision(2)),max:Number((s*6).toPrecision(2)),step:Number((s/50).toPrecision(1)),onChange:u=>u!==void 0&&u>0&&y(f.id,{size:u})}),Ke(ye,{label:"Rotation",value:Math.round((f.rotation??0)*180/Math.PI),min:-180,max:180,step:1,onChange:u=>y(f.id,{rotation:(u??0)*Math.PI/180})}),Ke(ye,{label:"Opacity",value:f.opacity??1,min:0,max:1,step:.05,onChange:u=>y(f.id,{opacity:u??1})})]})]},f.id))]})]})}import{MapPin as yh,Trash2 as wh}from"lucide-react";import{jsx as mt,jsxs as li}from"react/jsx-runtime";var Sh=e=>e.map(t=>t.toFixed(2)).join(", ");function Np({open:e,onToggle:t,cameraState:i,formattedCameraState:a,savedCameraPosition:o,onSaveCameraPosition:n,onGoToSavedCamera:d,onClearSavedCamera:s,onResetView:p,onFitScene:c}){let x=o?.position&&o?.target?o:null;return li(Ye,{title:"Saved view",open:e,onToggle:t,tooltip:"Stores the current camera for this object, so selecting it flies there.",children:[mt(xn,{label:"Camera",children:mt("code",{className:"rui-readout",children:i?a?.position:"Move the camera"})}),mt(xn,{label:"Looking at",children:mt("code",{className:"rui-readout",children:i?a?.target:"\u2013"})}),x?li("div",{className:"rui-listRow rui-listRow--saved",children:[li("span",{className:"rui-listRowMain",children:[mt("span",{className:"rui-listRowTitle",children:"Saved view"}),mt("code",{className:"rui-listRowMeta",children:Sh(x.position)})]}),li("span",{className:"rui-listRowActions rui-listRowActions--visible",children:[mt("button",{type:"button",className:"se-iconButton",onClick:d,title:"Fly to the saved view","aria-label":"Fly to the saved view",children:mt(yh,{size:13})}),mt("button",{type:"button",className:"se-iconButton",onClick:s,title:"Delete saved view","aria-label":"Delete saved view",children:mt(wh,{size:13})})]})]}):null,li(to,{children:[mt("button",{type:"button",className:"bb-button",onClick:n,disabled:!i,children:x?"Update view":"Save view"}),mt("button",{type:"button",className:"bb-button",onClick:p,children:"Reset camera"}),mt("button",{type:"button",className:"bb-button",onClick:c,children:"Fit scene"})]})]})}import{useLayoutEffect as kh,useRef as Ch,useState as Mh}from"react";import{RotateCcw as Ph}from"lucide-react";import{jsx as Qe,jsxs as Yo}from"react/jsx-runtime";var Op=["X","Y","Z"],Bh=.1,Th=.1,Ap=.01;function Ep(e){let t=e%360;return t<0?t+360:t}function Rh(e){return Ep(e*180/Math.PI)}function Nh(e){return e*Math.PI/180}function Ua({value:e,min:t=-1/0,max:i=1/0,step:a=.1,disabled:o=!1,onChange:n,formatValue:d=c=>Number(c.toFixed(3)),ariaLabel:s,className:p}){let c=d(e),[x,h]=Mh(String(c)),g=Ch(!1);return kh(()=>{g.current||h(String(c))},[c]),Qe("input",{type:"number",className:p,step:a,min:t===-1/0?void 0:t,max:i===1/0?void 0:i,value:x,disabled:o,"aria-label":s,onFocus:()=>{g.current=!0},onChange:C=>{let M=C.target.value;if(h(M),M===""||M==="-")return;let y=Number(M);if(Number.isFinite(y)){let T=Math.max(t,Math.min(i,y));n(T)}},onBlur:()=>{g.current=!1,h(String(d(e)))}})}function Ah({value:e,min:t=-1/0,max:i=1/0,step:a=.1,disabled:o=!1,onChange:n,formatValue:d=p=>Number(p.toFixed(3)),label:s}){return Qe("div",{className:"bb-transformAxesGrid",children:Op.map((p,c)=>Yo("div",{className:"bb-transformAxis",children:[Qe("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:p}),Qe("div",{className:"bb-transformAxisControl",children:Qe(Ua,{className:"se-numberInput bb-transformNumberInput",step:a,min:t,max:i,value:e[c],disabled:o,formatValue:d,ariaLabel:`${p} ${s?.toLowerCase()||""}`,onChange:x=>{let h=[...e];h[c]=x,n(h,c)}})})]},p))})}function jp({selectedItem:e,selectedBinding:t,open:i,onToggle:a,updateBinding:o,originalTransform:n,originalTransforms:d}){let s=t.transform?.rotation??n?.rotation??[0,0,0],p=t.transform?.position??n?.position??[0,0,0],c=n?.scale??[1,1,1],x=pa(t.transform?.scale??c,c),h=(f=e??"")=>d?.[f]??(f===e?n:null),g=(f,u)=>f.transform?.pivot??Ql(u?.pivotLocal??[0,0,0],f.transform?.rotation??u?.rotation??[0,0,0],f.transform?.scale??u?.scale??[1,1,1],u?.rotationOrder??"XYZ",f.transform?.shear),C=(f,u)=>{e&&o(e,(v,m)=>{let N=h(m),G=[...v.transform?.rotation??N?.rotation??[0,0,0]];return G[f]=Nh(Ep(u)),{...v,transform:{...v.transform,rotation:G,pivot:g(v,N)}}})},M=(f,u)=>{e&&o(e,(v,m)=>{let N=h(m),G=[...v.transform?.position??N?.position??[0,0,0]];return G[f]=u,{...v,transform:{...v.transform,position:G}}})},y=f=>{if(!e)return;let u=Math.max(Ap,f);o(e,(v,m)=>{let N=h(m),A=N?.scale??[1,1,1],G=v.transform?.scale??A,B=pa(G,A),P=B>0?G:A,$=u/(B||1);return{...v,transform:{...v.transform,scale:P.map(H=>H*$),pivot:g(v,N)}}})},T=()=>{!e||!n||o(e,f=>{let u={...f.transform};return delete u.position,delete u.rotation,delete u.scale,delete u.pivot,delete u.shear,{...f,transform:Object.keys(u).length>0?u:void 0}})};return Yo(Ye,{title:"Transform",open:i,onToggle:a,tooltip:"Rotation and scale keep the object's visible center fixed. Scale preserves its proportions.",children:[Yo("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.rotation",children:[Qe("span",{className:"se-fieldLabel",children:"Rotation"}),Qe("div",{className:"bb-transformAxesGrid",children:Op.map((f,u)=>{let v=Math.round(Rh(s[u]));return Yo("div",{className:"bb-transformAxis",children:[Qe("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:f}),Qe("div",{className:"bb-transformAxisControl",children:Qe(Ua,{className:"se-numberInput bb-transformNumberInput",step:1,min:0,max:359,value:v,disabled:!e,formatValue:m=>Math.round(m),ariaLabel:`${f} rotation in degrees`,onChange:m=>C(u,m)})})]},f)})})]}),Yo("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.position",children:[Qe("span",{className:"se-fieldLabel",children:"Position"}),Qe(Ah,{value:p,min:-1/0,max:1/0,step:Bh,disabled:!e,label:"position",onChange:(f,u)=>M(u,f[u])})]}),Yo("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.scale",children:[Qe("span",{className:"se-fieldLabel",children:"Scale"}),Qe(Ua,{className:"se-numberInput bb-transformNumberInput",step:Th,min:Ap,value:x,disabled:!e,formatValue:f=>Number(f.toFixed(2)),ariaLabel:"Uniform scale factor",onChange:y})]}),Qe(to,{children:Yo("button",{type:"button",className:"bb-button",disabled:!e||!n,onClick:T,title:"Restore this object's position, rotation, and scale to what they were in the original model",children:[Qe(Ph,{size:13,"aria-hidden":"true"}),"Restore original"]})})]})}import{memo as Wh}from"react";import{useEffect as Dp,useId as Oh,useLayoutEffect as Ka,useMemo as Nn,useRef as di,useState as An}from"react";import{Box as Eh,ChevronDown as jh,ChevronRight as Ih,ChevronsDownUp as zh,ChevronsUpDown as Lh,Focus as Dh,Folder as Fh,Lightbulb as Hh,ListChecks as $h,Trash2 as Uh}from"lucide-react";function Ip(e,t){let i=new Map(Object.entries(t).filter(([,d])=>!d.removed).map(([d,s])=>[s.modelObjectId??d,d])),a=new Set,o=new Map;for(let d of e){let s=d.objectId?i.get(d.objectId):void 0;s&&a.add(s),o.set(d.id,{id:d.id,name:d.name,key:s,children:[],keys:[]})}let n=[];for(let d of e){let s=o.get(d.id);((d.parentId?o.get(d.parentId):void 0)?.children??n).push(s)}for(let[d,s]of Object.entries(t))!s.removed&&!a.has(d)&&n.push({id:`binding:${d}`,name:s.modelObjectId??d,key:d,children:[],keys:[d]});for(let d=e.length-1;d>=0;d--){let s=o.get(e[d].id);s.children=s.children.filter(p=>p.keys.length),s.keys=[...s.key?[s.key]:[],...s.children.flatMap(p=>p.keys)]}return n.filter(d=>d.keys.length)}function zp(e,t,i){let a=i.trim().toLowerCase();if(!a)return e;let o=n=>{let d=n.key?t[n.key]:void 0;if([n.name,n.key,d?.label,d?.type,d?.group,...d?.tags??[]].join(" ").toLowerCase().includes(a))return n;let p=n.children.map(o).filter(c=>!!c);return p.length?{...n,key:void 0,children:p,keys:p.flatMap(c=>c.keys)}:null};return e.map(o).filter(n=>!!n)}function _a(e,t,i=!1){let a=[],o=e.slice().reverse().map(n=>({node:n,depth:0,parentId:null}));for(;o.length;){let n=o.pop();if(a.push(n),i||!t.has(n.node.id))for(let d=n.node.children.length-1;d>=0;d--)o.push({node:n.node.children[d],depth:n.depth+1,parentId:n.node.id})}return a}function Va(e,t){for(let i of e){if(i.key===t)return[];let a=Va(i.children,t);if(a)return[i.id,...a]}return null}function Lp(e,t,i,a,o){if(o.range){let n=i?a.indexOf(i):-1,d=a.indexOf(t);if(n>=0&&d>=0){let s=a.slice(Math.min(n,d),Math.max(n,d)+1);return[...new Set(o.additive?[...e,...s]:s)]}}return o.toggle||o.additive?e.includes(t)?e.filter(n=>n!==t):[...e,t]:[t]}import{jsx as ge,jsxs as ft}from"react/jsx-runtime";var _h=[],Vh=[],Kh=[],ao=24;function Gh({count:e,total:t,name:i,onChange:a}){let o=di(null);return Ka(()=>{o.current&&(o.current.indeterminate=e>0&&e<t)},[e,t]),ge("input",{ref:o,className:"bb-treeCheckbox",type:"checkbox","aria-label":`Select ${i}`,"aria-checked":e>0&&e<t?"mixed":e===t,checked:e===t&&t>0,onChange:a})}function mr({bindings:e,hierarchy:t=Vh,selectedItem:i,onSelect:a,onHover:o,fill:n,isolatedItem:d,onIsolate:s,multiSelectEnabled:p=!1,multiSelectedKeys:c=_h,onSetMultiSelected:x,selectionSets:h=Kh,onSelectionSetsChange:g,onToggleMultiSelect:C}){let[M,y]=An(""),[T,f]=An(()=>new Set),[u,v]=An(""),m=di(null),N=Nn(()=>Ip(t,e),[t,e]),A=Nn(()=>zp(N,e,M),[N,e,M]),G=Nn(()=>_a(A,T,!!M.trim()),[A,T,M]),B=Nn(()=>G.flatMap(({node:j})=>j.key?[j.key]:[]),[G]),P=Nn(()=>A.flatMap(j=>j.keys),[A]),$=di(null);Dp(()=>{if($.current===i)return;let j=i?Va(N,i):null;i&&!j||($.current=i,j?.length&&f(J=>{if(!j.some(Ce=>J.has(Ce)))return J;let L=new Set(J);return j.forEach(Ce=>L.delete(Ce)),L}))},[i,N]);let H=Nn(()=>new Set(p||c.length>0?c:i?[i]:[]),[p,c,i]),de=P.length>0&&P.every(j=>H.has(j)),_=j=>{let J=j.every(Ce=>H.has(Ce)),L=new Set(j);x?.(J?[...H].filter(Ce=>!L.has(Ce)):[...new Set([...H,...j])])},Q=j=>f(J=>{let L=new Set(J);return L.has(j)?L.delete(j):L.add(j),L}),w=(j,J)=>{let L=j.node.key;if(!L){Q(j.node.id);return}x&&(p||J.shiftKey||J.ctrlKey||J.metaKey)?x(Lp([...H],L,m.current??i,B,{range:J.shiftKey,additive:J.ctrlKey||J.metaKey,toggle:p&&!J.shiftKey})):a(L),J.shiftKey||(m.current=L)},I=j=>{let J=new Set(j.objectIds);return Object.keys(e).filter(L=>!e[L].removed&&J.has(e[L].modelObjectId??L))},he=St(it().tier,"selectionSets",h.length),Ne=()=>{let j=[...H].filter(J=>e[J]&&!e[J].removed);!j.length||!u.trim()||h.length>=128||!he||(g?.([...h,{id:crypto.randomUUID(),name:u.trim(),objectIds:j.map(J=>e[J].modelObjectId??J)}]),v(""))};return ft("section",{className:`bb-nodeList ${n?"bb-nodeList--fill":""}`,children:[ft("div",{className:"bb-outlinerHead",children:[ge("div",{className:"bb-search",children:ge("input",{className:"bb-input","aria-label":"Filter objects",placeholder:"Filter objects",value:M,onChange:j=>y(j.target.value)})}),C&&ge("button",{type:"button",className:`bb-treeIcon ${p?"bb-treeIcon--active":""}`,"aria-pressed":p,"aria-label":"Toggle multi-select",title:p?"Multi-select on: edits apply to every selected object":"Select multiple objects",onClick:C,children:ge($h,{size:14})}),ge("button",{type:"button",className:"bb-treeIcon","aria-label":"Expand all",title:"Expand all",onClick:()=>f(new Set),children:ge(Lh,{size:14})}),ge("button",{type:"button",className:"bb-treeIcon","aria-label":"Collapse all",title:"Collapse all",onClick:()=>f(new Set(_a(N,new Set,!0).filter(({node:j})=>j.children.length).map(({node:j})=>j.id))),children:ge(zh,{size:14})})]}),x&&M.trim()&&P.length>0&&ft("div",{className:"bb-selectionModeBar bb-selectionModeBar--matches",children:[ft("span",{children:[P.length," ",P.length===1?"match":"matches"]}),ge("button",{type:"button",className:"bb-button bb-button--small",onClick:()=>_(P),children:de?"Clear":"Select all"})]}),ge(qh,{rows:G,revealKey:i,bindings:e,selected:H,multiSelect:p,collapsed:T,searching:!!M.trim(),search:M,onSelect:w,onToggle:Q,onToggleKeys:x?_:void 0,onSelectAll:x?()=>x(P):void 0,onHover:o,isolatedItem:d,onIsolate:s}),g&&ft("details",{className:"bb-selectionSets",children:[ft("summary",{children:["Saved selections",h.length?` (${h.length})`:""]}),ft("div",{className:"bb-selectionSetCreate",children:[ge("input",{className:"bb-input","aria-label":"Selection name",placeholder:"Name this selection",maxLength:200,value:u,onChange:j=>v(j.target.value),onKeyDown:j=>{j.key==="Enter"&&(j.preventDefault(),Ne())}}),ge("button",{type:"button",className:"bb-button bb-button--ghost",disabled:!H.size||!u.trim()||h.length>=128||!he,title:he?void 0:"Saving more selections requires the Starter plan or higher.",onClick:Ne,children:"Save"})]}),!h.length&&ge("p",{children:"Select objects, then save the selection to reuse it."}),h.map(j=>{let J=I(j);return ft("div",{className:"bb-selectionSetRow",children:[ft("button",{type:"button",className:"bb-button bb-button--ghost",disabled:!J.length,title:J.length<j.objectIds.length?`${j.objectIds.length-J.length} objects unavailable`:void 0,onClick:()=>{y(""),f(new Set),x?.(J),m.current=J[0]??null},children:[j.name,ft("small",{children:[J.length," / ",j.objectIds.length]})]}),ge("button",{type:"button",className:"bb-treeIcon","aria-label":`Delete selection ${j.name}`,onClick:()=>g(h.filter(L=>L.id!==j.id)),children:ge(Uh,{size:14})})]},j.id)})]})]})}function qh({rows:e,revealKey:t,bindings:i,selected:a,multiSelect:o,collapsed:n,searching:d,search:s,onSelect:p,onToggle:c,onToggleKeys:x,onSelectAll:h,onHover:g,isolatedItem:C,onIsolate:M}){let y=di(null),[T,f]=An(400),[u,v]=An(0),[m,N]=An(0),A=Oh();Ka(()=>{let _=y.current;if(!_)return;let Q=new ResizeObserver(()=>f(_.clientHeight));return Q.observe(_),()=>Q.disconnect()},[]),Dp(()=>{y.current&&(y.current.scrollTop=0),v(0),N(0)},[s]);let G=_=>{_=Math.max(0,Math.min(e.length-1,_)),N(_);let Q=y.current;Q&&(_*ao<Q.scrollTop?Q.scrollTop=_*ao:(_+1)*ao>Q.scrollTop+Q.clientHeight&&(Q.scrollTop=(_+1)*ao-Q.clientHeight))},B=di(null);Ka(()=>{if(B.current===t)return;if(!t){B.current=null;return}let _=e.findIndex(({node:Q})=>Q.key===t);_<0||(B.current=t,G(_))});let P=_=>{let Q=e[Math.min(m,e.length-1)];if(Q){if((_.ctrlKey||_.metaKey)&&_.key.toLowerCase()==="a"){_.preventDefault(),_.stopPropagation(),h?.();return}if(["ArrowDown","ArrowUp","ArrowLeft","ArrowRight","Home","End","Enter"," "].includes(_.key)){if(_.preventDefault(),_.stopPropagation(),_.key==="ArrowDown"&&G(m+1),_.key==="ArrowUp"&&G(m-1),_.key==="Home"&&G(0),_.key==="End"&&G(e.length-1),_.key==="ArrowRight"&&Q.node.children.length&&(n.has(Q.node.id)?c(Q.node.id):G(m+1)),_.key==="ArrowLeft")if(Q.node.children.length&&!n.has(Q.node.id))c(Q.node.id);else{let w=e.findIndex(I=>I.node.id===Q.parentId);w>=0&&G(w)}(_.key==="Enter"||_.key===" ")&&(_.key===" "&&o&&!Q.node.key?x?.(Q.node.keys):p(Q,_))}}},$=Math.max(0,Math.min(e.length-1,Math.floor(u/ao))-5),H=Math.min(e.length,$+Math.ceil(T/ao)+12),de=Math.min(m,e.length-1);return ft("div",{ref:y,className:"bb-sceneTree",role:"tree","aria-label":"Scene hierarchy","aria-multiselectable":!!h,tabIndex:0,"aria-activedescendant":de>=$&&de<H?`${A}-${de}`:void 0,onKeyDown:P,onScroll:_=>v(_.currentTarget.scrollTop),children:[!e.length&&ge("p",{className:"bb-treeEmpty",children:"No matching objects."}),ge("div",{style:{height:e.length*ao,position:"relative"},children:e.slice($,H).map((_,Q)=>{let{node:w,depth:I}=_,he=$+Q,Ne=w.key?i[w.key]:void 0,j=w.keys.reduce((Ce,tn)=>Ce+Number(a.has(tn)),0),J=w.children.length?d||!n.has(w.id):void 0,L=w.key?a.has(w.key):j===w.keys.length;return ft("div",{id:`${A}-${he}`,role:"treeitem","aria-level":I+1,"aria-expanded":J,"aria-selected":L,className:`bb-treeRow${L?" bb-treeRow--selected":""}${w.key?" bb-treeRow--object":""}`,style:{top:he*ao,height:ao,paddingLeft:4+Math.min(I,10)*12},onFocus:()=>N(he),onMouseEnter:()=>g?.(w.key??null),onMouseLeave:()=>g?.(null),children:[w.children.length?ge("button",{type:"button",tabIndex:-1,className:"bb-treeIcon","aria-label":`${J?"Collapse":"Expand"} ${w.name}`,onClick:()=>c(w.id),children:J?ge(jh,{size:13}):ge(Ih,{size:13})}):ge("span",{className:"bb-treeSpacer"}),o&&x&&ge(Gh,{count:j,total:w.keys.length,name:w.name,onChange:()=>x(w.keys)}),ft("button",{type:"button",tabIndex:-1,className:"bb-treeNode",onClick:Ce=>{N(he),y.current?.focus({preventScroll:!0}),p(_,Ce)},children:[Ne?Ne.type==="light"?ge(Hh,{size:13,"aria-hidden":"true"}):ge(Eh,{size:13,"aria-hidden":"true"}):ge(Fh,{size:13,"aria-hidden":"true"}),ge("span",{title:Ne?`${Ne.type??"other"} \xB7 ${Ne.modelObjectId}`:void 0,children:Ne?.label||w.name}),Ne?null:ge("small",{children:w.keys.length})]}),w.key&&M&&ge("button",{type:"button",tabIndex:-1,className:"bb-treeIcon bb-treeIsolate","aria-label":`${C===w.key?"Show all":"Isolate"} ${w.name}`,"aria-pressed":C===w.key,onClick:()=>M(C===w.key?null:w.key),children:ge(Dh,{size:13})})]},w.id)})})]})}import{Fragment as Xh,jsx as Jo,jsxs as Ga}from"react/jsx-runtime";var qa=[],Fp=Wh(Yh);function Wa(e){let t=0;for(let i of Object.values(e))i.removed||(t+=1);return t}function Yh({bindings:e,selectedItem:t,onSelect:i,onHover:a,modelGroups:o,onSelectModel:n,isolatedItem:d=null,onIsolate:s,multiSelectEnabled:p=!1,onToggleMultiSelect:c,onExitMultiSelect:x,multiSelectedKeys:h=qa,onSetMultiSelected:g,hierarchy:C,selectionSets:M,onSelectionSetsChange:y}){let T=o&&o.length>=2?o:null,f=T?T.reduce((u,v)=>u+Wa(v.bindings),0):Wa(e);return Ga(Xh,{children:[p&&Ga("div",{className:"bb-selectionModeBar",children:[Ga("span",{children:[h.length," of ",f," selected"]}),Jo("button",{type:"button",className:"bb-button bb-button--small","aria-label":"Exit multi-select",onClick:x??c,children:"Done"})]}),T?Jo(Jh,{groups:T,selectedItem:t,onSelect:i,onHover:a,onSelectModel:n,isolatedItem:d,onIsolate:s,multiSelectEnabled:p,multiSelectedKeys:h,onSetMultiSelected:g,onToggleMultiSelect:c,hierarchy:C,selectionSets:M,onSelectionSetsChange:y}):Jo(mr,{bindings:e,selectedItem:t,onSelect:i,onHover:a,isolatedItem:d,onIsolate:s,multiSelectEnabled:p,multiSelectedKeys:h,onSetMultiSelected:g,onToggleMultiSelect:c,hierarchy:C,selectionSets:M,onSelectionSetsChange:y})]})}function Jh({groups:e,selectedItem:t,onSelect:i,onHover:a,onSelectModel:o,isolatedItem:n=null,onIsolate:d,multiSelectEnabled:s=!1,multiSelectedKeys:p=qa,onSetMultiSelected:c,onToggleMultiSelect:x,hierarchy:h,selectionSets:g,onSelectionSetsChange:C}){return Jo("section",{className:"bb-nodeList bb-nodeList--grouped",children:e.map(M=>{let y=M.isActive,T=Wa(M.bindings),f=`${M.label} (${T})${M.isActive?" \xB7 Active":""}`,u=y;return Jo("div",{className:`bb-groupItem ${u?"bb-groupItem--fill":""}`,children:Jo(Ye,{title:f,open:y,onToggle:()=>{o?.(M.url)},children:Jo(mr,{bindings:M.bindings,hierarchy:M.isActive?h:void 0,selectionSets:M.isActive?g:void 0,onSelectionSetsChange:M.isActive?C:void 0,selectedItem:t,onSelect:v=>{o?.(M.url),i(v)},onHover:a,fill:u,isolatedItem:M.isActive?n:null,onIsolate:M.isActive?d:void 0,multiSelectEnabled:M.isActive&&s,multiSelectedKeys:M.isActive?p:qa,onSetMultiSelected:M.isActive?c:void 0,onToggleMultiSelect:M.isActive?x:void 0})})},M.url)})})}import{jsx as Ya,jsxs as Zh}from"react/jsx-runtime";function Ja({title:e,label:t,open:i,onToggle:a,draft:o,error:n,example:d,onDraftChange:s,onCommit:p}){return Ya(Ye,{title:e,open:i,onToggle:a,children:Zh("div",{className:"rui-stack",children:[Ya("textarea",{className:"bb-textarea","aria-label":t,placeholder:d,value:o,onChange:c=>s(c.target.value),onBlur:p}),n?Ya("span",{className:"bb-note bb-note--error",children:n}):null]})})}import{useCallback as Pt}from"react";import{PropertyBinding as Up}from"three";import{PropertyBinding as Xa}from"three";function Hp(e){let t=new Map;return e.map(i=>{let a=(t.get(i)??0)+1;return t.set(i,a),a===1?i:`${i} (${a})`})}function Xo(e,t,i=[],a={},o=new Set(Object.keys(Ui(e).nodesById))){let n=new Map(Object.entries(t).filter(([,g])=>g.removed===!0).map(([g,C])=>[C.modelObjectId??g,C])),d=new Set(Object.entries(a).map(([g,C])=>C.modelObjectId??g)),s=i.filter(g=>g.loadState==="loading").map(g=>Xa.sanitizeNodeName(`${Gt(g.namePrefix)}_`)),p=Object.fromEntries(Object.entries(t).filter(([g,C])=>{let M=C.modelObjectId??g;return!d.has(M)&&(C.removed===!0||o.has(M)||s.some(y=>M.startsWith(y)))})),c=Object.fromEntries(Object.entries(a).map(([g,C])=>[g,n.get(C.modelObjectId??g)??C])),x={...p,...c},h=Object.keys(x);return h.length===Object.keys(t).length&&h.every(g=>x[g]===t[g])?t:x}function Gt(e){return e.replace(/\.[^./\\]+$/,"")}function Za(e,t,i={}){let a=Xa.sanitizeNodeName(Gt(e)).replace(/_/g,"-")||"Model",o=t.map(s=>Xa.sanitizeNodeName(Gt(s.namePrefix))),n=Object.entries(i).map(([s,p])=>p.modelObjectId??s),d=a;for(let s=2;;s++){let p=`${d}_`;if(!o.some(c=>c===d||c.startsWith(p))&&!n.some(c=>c.startsWith(p)))return d;d=`${a}-${s}`}}function On(e){e.resolved.cleanup()}function ci(e){e.resolved?.cleanup(),e.mergedModelSources.forEach(On)}function pi(e,t){let i=ad(e),a=Yn(i,Xi(e));if(t){let n=new Map(Object.values(t).map(d=>[d.modelObjectId,d]));for(let d of i){let s=n.get(d);s&&(a[d]=s)}}e.updateMatrixWorld(!0);let o={};for(let n of i){let d=Gn(e,n);if(!d){o[n]={position:[0,0,0],rotation:[0,0,0],scale:[1,1,1],pivotLocal:[0,0,0],rotationOrder:"XYZ"};continue}let s=Zl(d);o[n]={position:[d.position.x,d.position.y,d.position.z],rotation:[d.rotation.x,d.rotation.y,d.rotation.z],scale:[d.scale.x,d.scale.y,d.scale.z],pivotLocal:[s.x,s.y,s.z],rotationOrder:d.rotation.order}}return{bindings:a,originalTransforms:o,nodeNames:i}}function Qh(e,t){let i=e;for(;i;){if(i===t)return!0;i=i.parent}return!1}function Qa(e,t){let i=e.parent??e,a=pi(i,t),o=a.nodeNames.filter(n=>{let d=Gn(i,n);return d?Qh(d,e):!1});return{bindings:Object.fromEntries(o.map(n=>[n,a.bindings[n]])),originalTransforms:Object.fromEntries(o.map(n=>[n,a.originalTransforms[n]])),nodeNames:o}}function fr(e,t=[]){let i={bindings:e,mergeSources:t};return{past:[],present:i,future:[],baseline:i,edits:0}}function _p(e,t){let i=t(e.present),a=e.past.map(t),o=e.future.map(t),n=t(e.baseline);return i===e.present&&n===e.baseline&&a.every((d,s)=>d===e.past[s])&&o.every((d,s)=>d===e.future[s])?e:{...e,present:i,past:a,future:o,baseline:n}}function Vp(e,t,i,a={}){return _p(e,o=>{if(!o.mergeSources.some(s=>s.url===t))return o;let n=new Map(Object.entries(o.bindings).map(([s,p])=>[p.modelObjectId??s,p])),d={...o.bindings};for(let[s,p]of Object.entries(a))d[s]=n.get(p.modelObjectId??s)??p;return{bindings:d,mergeSources:o.mergeSources.map(s=>s.url===t?{...s,...i}:s)}})}function es(e,t){let i=e.mergeSources.find(n=>n.url===t);if(!i)return e;let a=new Set(i.nodeNames),o=Up.sanitizeNodeName(`${Gt(i.namePrefix)}_`);return{mergeSources:e.mergeSources.filter(n=>n.url!==t),bindings:Object.fromEntries(Object.entries(e.bindings).filter(([n,d])=>{let s=d.modelObjectId??n;return!a.has(s)&&!a.has(n)&&!s.startsWith(o)}))}}function ts(e,t){let i=io(e.bindingHistory??fr(e.bindings,e.mergedModelSources),{type:"set",updater:t,track:!0,coalesce:!1});return{...e,bindings:i.present.bindings,mergedModelSources:i.present.mergeSources,bindingHistory:i}}function os(e,t,i,a){let o=Vp(e.bindingHistory??fr(e.bindings,e.mergedModelSources),t,i,a);return{...e,bindings:o.present.bindings,mergedModelSources:o.present.mergeSources,bindingHistory:o}}function Kp(e,t){let i=e.bindingHistory??fr(e.bindings,e.mergedModelSources),o=[i.present,...i.past,...i.future].flatMap(s=>s.mergeSources).map(s=>Up.sanitizeNodeName(`${Gt(s.namePrefix)}_`)),n=Object.fromEntries(Object.entries(t).filter(([s,p])=>!o.some(c=>(p.modelObjectId??s).startsWith(c)))),d=_p(i,s=>({...s,bindings:{...n,...s.bindings}}));return{...e,bindings:d.present.bindings,bindingHistory:d}}function $p(e,t){let i=new Set(t.mergeSources.map(a=>a.url));return{...e,present:{...e.present,mergeSources:e.present.mergeSources.map(a=>i.has(a.url)?a:{...a,loadState:"loading"})}}}function Gp(e,t=[]){let i=ti({bindings:e,mergeSources:t}),{setValue:a,setValueAsStep:o,updateHistory:n,restoreSnapshot:d}=i,s=Pt(v=>a(m=>{let N=typeof v=="function"?v(m.bindings):v;return N===m.bindings?m:{...m,bindings:N}}),[a]),p=Pt(v=>o(m=>{let N=typeof v=="function"?v(m.bindings):v;return N===m.bindings?m:{...m,bindings:N}}),[o]),c=Pt(v=>n(m=>{let N=typeof v=="function"?v(m.present.bindings):v;if(N===m.present.bindings)return m;let A={...m.present,bindings:N};return{...m,present:A,baseline:m.edits===0?A:m.baseline}}),[n]),x=Pt(v=>n(m=>{let N=typeof v=="function"?v(m.present.mergeSources):v,A={...m.present,mergeSources:N};return{...m,present:A,baseline:m.edits===0?A:m.baseline}}),[n]),h=Pt(v=>o(m=>({...m,mergeSources:[...m.mergeSources,typeof v=="function"?v(m):v]})),[o]),g=Pt(v=>o(m=>es(m,v)),[o]),C=Pt((v,m,N)=>{n(A=>Vp(A,v,m,N))},[n]),M=Pt(()=>d(v=>{let m=io(v,{type:"undo"});return m===v?v:$p(m,v.present)}),[d]),y=Pt(()=>d(v=>{let m=io(v,{type:"redo"});return m===v?v:$p(m,v.present)}),[d]),T=Pt((v,m)=>d(N=>io(N,{type:"reset",value:{bindings:v,mergeSources:N.present.mergeSources},track:m?.asEdit??!1})),[d]),f=Pt(()=>d(v=>io(v,{type:"reset",value:v.present,track:!1})),[d]),u=Pt(v=>d({...v.bindingHistory??fr(v.bindings,v.mergedModelSources),present:{bindings:v.bindings,mergeSources:v.mergedModelSources}}),[d]);return{value:i.value.bindings,baseline:i.baseline.bindings,mergeSources:i.value.mergeSources,snapshot:i.snapshot,edits:i.edits,canUndo:i.canUndo,canRedo:i.canRedo,setValue:s,setValueAsStep:p,setValueUntracked:c,setMergeSourcesUntracked:x,addMerge:h,removeMerge:g,hydrateMerge:C,undo:M,redo:y,reset:T,clearHistory:f,restoreModel:u}}import{useEffect as qp,useRef as ex}from"react";function Wp(e,t,{modelUrl:i,modelSourceRef:a,uploadedFilesRef:o}={}){let n=ex(new Map);qp(()=>{let d=new Map,s=x=>{for(let h of[x.present,...x.past,...x.future])h.mergeSources.forEach(g=>d.set(g.url,g))};s(e);for(let x of t)x.bindingHistory&&s(x.bindingHistory),x.mergedModelSources.forEach(h=>d.set(h.url,h));for(let[x,h]of n.current)d.has(x)||h.resolved.cleanup();n.current=d;let p=new Set,c=x=>{x?.kind==="file"&&p.add(x.key)};i&&c(a?.current?.model),t.forEach(x=>c(x.sessionModel)),d.forEach(x=>c(x.sessionModel));for(let x of o?.current.keys()??[])p.has(x)||o?.current.delete(x)},[e,t,i,a,o]),qp(()=>()=>{n.current.forEach(d=>d.resolved.cleanup()),n.current.clear(),o?.current.clear()},[o])}import{useCallback as tx,useEffect as ns,useRef as ox}from"react";var nx=500;function Yp({composition:e,autosaveEnabled:t,hasEdits:i,modelUrl:a,bindings:o,sceneConfig:n,parkedModels:d,mergedModelSources:s,modelOrder:p,onTextureUpload:c,modelSourceRef:x,pendingLoadRef:h,storedModelKeysRef:g,uploadedFilesRef:C,pendingAutosaveRef:M,autosaveFailureShownRef:y,setStatusMessage:T,setStatusTone:f}){let u=ox(0),v=tx(async(m,N)=>{if(c)return c(m,N);let A=URL.createObjectURL(m);if(t)try{await wn(A,m)}catch(G){console.warn("[BindingBuilder] Could not store texture file for autosave:",G)}return A},[c,t]);return ns(()=>{if(!t||!i){M.current=null;return}let m=x.current;if(a&&!m){M.current=null;return}let N=a,A=()=>{if(M.current!==A||h.current)return;M.current=null;let B=++u.current,P=j=>{console.warn("[BindingBuilder] Autosave failed:",j),!y.current&&(y.current=!0,T("Couldn't autosave this session \u2014 the browser refused to store it, possibly for lack of space. Export your work to keep it."),f("error"))};if(!N||!m){g.current.clear(),$d().then(()=>{B===u.current&&(y.current=!1)}).catch(P);return}let{model:$}=m,H=[],de=new Set,_=j=>{if(!j||j.kind!=="file"||(de.add(j.key),g.current.has(j.key)))return;let J=C.current.get(j.key);J&&H.push({key:j.key,file:J})};_($),d.forEach(j=>{_(j.sessionModel),j.mergedModelSources.forEach(J=>_(J.sessionModel))}),s.forEach(j=>_(j.sessionModel)),g.current=new Set([...g.current].filter(j=>de.has(j)));let Q=j=>({model:j.sessionModel,namePrefix:j.namePrefix}),w=d.filter(j=>!!j.sessionModel).map(j=>({model:j.sessionModel,bindings:j.bindings,originalTransforms:j.originalTransforms,modelSettings:j.modelSettings,mergeModels:j.mergedModelSources.map(Q)})),I=s.map(Q),he=new Map;he.set(N,$),d.forEach(j=>{j.sessionModel&&he.set(j.url,j.sessionModel)});let Ne=p.map(j=>{let J=he.get(j);return J?Ut(J):null}).filter(j=>j!==null);Fd({model:$,composition:e,bindings:o,sceneConfig:n,parkedModels:w,mergeModels:I,modelOrder:Ne},H).then(()=>{B===u.current&&(g.current=de,y.current=!1)}).catch(P)};if(M.current=A,!N){A();return}let G=window.setTimeout(A,nx);return()=>window.clearTimeout(G)},[e,t,i,a,o,n,d,s,p]),ns(()=>{if(!t)return;let m=()=>M.current?.(),N=()=>{document.visibilityState==="hidden"&&m()};return window.addEventListener("pagehide",m),document.addEventListener("visibilitychange",N),()=>{window.removeEventListener("pagehide",m),document.removeEventListener("visibilitychange",N),m()}},[t]),ns(()=>{if(!t||!a||!i)return;let m=N=>{M.current?.(),N.preventDefault(),N.returnValue=""};return window.addEventListener("beforeunload",m),()=>window.removeEventListener("beforeunload",m)},[t,a,i]),{handleTextureUpload:v}}import{useCallback as is,useEffect as ix,useRef as Zo}from"react";var rs=640,as=360,rx=.82,ax=4e3,sx=2*6e4,Jp=1e3,lx=6e4;function dx({now:e,lastActivityAt:t,lastCaptureAt:i,ready:a,loadingTiles:o}){if(!a)return Jp;let n=e-t;return o&&n<lx?Jp:Math.max(ax-n,sx-(e-i),0)}async function cx(e){let t=new Image;t.src=e,await t.decode();let i=document.createElement("canvas");i.width=rs,i.height=as;let a=Math.max(rs/t.naturalWidth,as/t.naturalHeight),o=t.naturalWidth*a,n=t.naturalHeight*a,d=i.getContext("2d");if(!d)throw new Error("No 2D canvas to draw the thumbnail on.");return d.imageSmoothingQuality="high",d.drawImage(t,(rs-o)/2,(as-n)/2,o,n),new Promise((s,p)=>{i.toBlob(c=>c?s(c):p(new Error("Could not encode the thumbnail.")),"image/jpeg",rx)})}function Xp({onCapture:e,hasThumbnail:t,viewerRef:i,isModelLoading:a}){let o=Zo(e);o.current=e;let n=Zo(a);n.current=a;let d=Zo(!1),s=Zo(!1),p=Zo(null),c=Zo(0),x=Zo(Number.NEGATIVE_INFINITY),h=is(()=>{if(!o.current||!d.current||s.current||p.current!==null)return;let y=i.current,T=Date.now(),f=dx({now:T,lastActivityAt:c.current,lastCaptureAt:x.current,ready:!!y&&!n.current()&&document.visibilityState==="visible",loadingTiles:y?.isLoadingTiles()??!1});if(f>0){p.current=window.setTimeout(()=>{p.current=null,h()},f);return}s.current=!0,d.current=!1,x.current=T,y.captureImage({type:"image/jpeg",quality:.92}).then(cx).then(u=>o.current?.(u)).catch(u=>{d.current=!0,console.warn("[react-immersive] Could not update the project thumbnail.",u)}).finally(()=>{s.current=!1,h()})},[i]),g=is(()=>{c.current=Date.now()},[]),C=is(()=>{g(),d.current=!0,h()},[g,h]),M=!!e;return ix(()=>{if(!M)return;c.current=Date.now(),t||(d.current=!0),h();let y=["pointermove","pointerdown","keydown","wheel"];for(let T of y)window.addEventListener(T,g,{passive:!0,capture:!0});return()=>{for(let T of y)window.removeEventListener(T,g,{capture:!0});p.current!==null&&window.clearTimeout(p.current),p.current=null}},[M,t,g,h]),{markThumbnailOutdated:C,noteThumbnailActivity:g}}import{useLayoutEffect as px}from"react";function Zp({bindings:e,multiSelectMode:t,selectedItem:i,multiSelectedKeys:a,setSelectedItem:o,setMultiSelectedKeys:n}){px(()=>{let d=p=>!!(e[p]&&!e[p].removed),s=a.filter(d);s.length!==a.length&&n(s),i&&(!d(i)||t&&!s.includes(i))&&o(t?s[s.length-1]??null:null)},[e,t,i,a,o,n])}import{useCallback as Bo,useReducer as ux}from"react";var ls={selectedItem:null,keys:[],checkboxMode:!1},ss=(e,t)=>typeof e=="function"?e(t):e;function bx(e,t){if(t.type==="primary"){let p=ss(t.value,e.selectedItem);return p===e.selectedItem?e:{...e,selectedItem:p}}if(t.type==="keys"){let p=ss(t.value,e.keys);return p===e.keys?e:{...e,keys:p}}if(t.type==="mode"){let p=ss(t.value,e.checkboxMode);return p===e.checkboxMode?e:{...e,checkboxMode:p}}if(t.type==="clear")return ls;if(t.type==="exitMode"||t.type==="toggleMode"&&e.checkboxMode)return{...e,checkboxMode:!1,keys:[]};if(t.type==="toggleMode")return{...e,checkboxMode:!0,keys:e.keys.length?e.keys:e.selectedItem?[e.selectedItem]:[]};if(t.type==="selection"){let p=[...new Set(t.keys)];return{...e,keys:p,selectedItem:e.selectedItem&&p.includes(e.selectedItem)?e.selectedItem:p[p.length-1]??null}}if(t.type!=="select")return e;let{key:i,modifiers:a}=t;if(!i)return e.checkboxMode?e:ls;if(!e.checkboxMode&&!a.shiftKey&&!a.ctrlKey&&!a.metaKey)return{...e,selectedItem:i,keys:[]};let o=e.keys.length?e.keys:e.selectedItem?[e.selectedItem]:[],n=a.shiftKey&&!a.ctrlKey&&!a.metaKey,d=o.includes(i)&&!n,s=d?o.filter(p=>p!==i):[...new Set([...o,i])];return{...e,keys:s,selectedItem:d?e.selectedItem&&s.includes(e.selectedItem)?e.selectedItem:s[s.length-1]??null:i}}function Qp(){let[e,t]=ux(bx,ls),i=Bo(x=>t({type:"primary",value:x}),[]),a=Bo(x=>t({type:"keys",value:x}),[]),o=Bo(x=>t({type:"mode",value:x}),[]),n=Bo(x=>t({type:"selection",keys:x}),[]),d=Bo((x,h={})=>t({type:"select",key:x,modifiers:h}),[]),s=Bo(()=>t({type:"toggleMode"}),[]),p=Bo(()=>t({type:"exitMode"}),[]),c=Bo(()=>t({type:"clear"}),[]);return{selectedItem:e.selectedItem,multiSelectedKeys:e.keys,multiSelectMode:e.checkboxMode,groupSelectionActive:e.checkboxMode||e.keys.length>1,setSelectedItem:i,setMultiSelectedKeys:a,setMultiSelectMode:o,setSelection:n,selectObject:d,toggleMultiSelect:s,exitMultiSelect:p,clearSelection:c}}import{useCallback as eu,useEffect as gx,useState as mx}from"react";function tu(e,t){let[i,a]=mx(!1),o=e>0||t>0,n=eu(()=>a(!0),[]),d=eu(()=>a(!1),[]);return gx(()=>{o&&n()},[o,n]),{hasEdits:i||o,markSessionEdited:n,resetSessionEdits:d}}import{useEffect as ou,useReducer as fx,useRef as nu}from"react";function iu({enabled:e=!0,modelUrl:t,bindings:i,mergeSources:a,parkedModels:o,scenesRef:n,sceneRevision:d,setBindings:s,setParkedModels:p}){let[c,x]=fx(C=>C+1,0),h=nu(new WeakMap),g=nu(new WeakMap);ou(()=>{if(!e)return;let C=[t,...o.map(T=>T.url)],M=new Set(C.flatMap(T=>{let f=T?n.current.get(T):void 0;return f?[f]:[]})),y=T=>{T.target&&h.current.delete(T.target),x()};for(let T of M)T.addEventListener("childadded",y),T.addEventListener("childremoved",y);return()=>{for(let T of M)T.removeEventListener("childadded",y),T.removeEventListener("childremoved",y)}},[e,t,o,n,d]),ou(()=>{if(!e)return;let C=T=>{let f=h.current.get(T);return f||(f=new Set(Object.keys(Ui(T).nodesById)),h.current.set(T,f)),f},M=(T,f)=>{let u=C(T),v=g.current.get(T)??new Set;g.current.set(T,v);for(let[m,N]of Object.entries(f))N.removed&&v.add(N.modelObjectId??m);for(let m of v)u.has(m)&&v.delete(m);return v.size?new Set([...u,...v]):u},y=t?n.current.get(t):void 0;if(y){let T=M(y,i);s(f=>Xo(y,f,a,{},T))}p(T=>{let f=!1,u=T.map(v=>{let m=n.current.get(v.url);if(!m)return v;let N=Xo(m,v.bindings,v.mergedModelSources,{},M(m,v.bindings));return N===v.bindings?v:(f=!0,{...v,bindings:N})});return f?u:T})},[e,t,i,a,o,n,d,c,s,p])}import{useEffect as hx,useMemo as xx,useReducer as vx}from"react";function ru({modelUrl:e,scenesRef:t,sceneRevision:i,streaming:a=!1}){let o=e?t.current.get(e):void 0,[n,d]=vx(s=>s+1,0);return hx(()=>{if(!o||a)return;let s=()=>d();return o.addEventListener("childadded",s),o.addEventListener("childremoved",s),()=>{o.removeEventListener("childadded",s),o.removeEventListener("childremoved",s)}},[o,a]),xx(()=>({materialVariantGroups:o?_l(o):[],objectsWithoutUvs:o&&!a?Xi(o):new Set,hierarchy:o&&!a?Sd(o):[]}),[o,i,n,a])}import{AlertTriangle as yx,Box as wx,History as Sx,Trash2 as kx,Upload as Cx}from"lucide-react";import{useId as au,useState as Mx}from"react";import{Fragment as ui,jsx as pe,jsxs as $e}from"react/jsx-runtime";function Px(e){let t=new Date(e);return t.toDateString()===new Date().toDateString()?`today at ${t.toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}`:t.toLocaleString([],{dateStyle:"medium",timeStyle:"short"})}var ds=pe(yx,{size:15,"aria-hidden":"true"});function Ft({variant:e,...t}){return pe("button",{type:"button",className:`bb-dialogButton ${e?`bb-dialogButton--${e}`:""}`,...t})}function su({target:e,onCancel:t,onConfirm:i}){return $e(vn,{title:`Reset ${e==="bindings"?"object changes":e==="assets"?"asset placements":"scene settings"}?`,icon:ds,onCancel:t,footer:$e(ui,{children:[pe(Ft,{onClick:t,children:"Cancel"}),pe(Ft,{variant:"danger",onClick:i,autoFocus:!0,children:"Reset"})]}),children:[pe("p",{children:e==="bindings"?"This removes your changes to object properties, groups, tags, transforms, materials, actions, saved views, metrics, and metadata.":e==="assets"?"This resets every asset's position, rotation, and scale, and the grid spacing. Which assets are in the scene, their names, visibility, and object edits stay.":"This restores camera, lighting, environment, background, animations, annotations, and every other scene setting to their defaults."}),pe("p",{children:e==="assets"?"You can undo this.":"You can't undo this."})]})}function lu({models:e,savedAt:t,onCancel:i,onConfirm:a}){return $e(vn,{title:"Restore last session",icon:pe(Sx,{size:15,className:"bb-dialogIconNeutral","aria-hidden":"true"}),onCancel:i,footer:$e(ui,{children:[pe(Ft,{onClick:i,children:"Cancel"}),pe(Ft,{variant:"primary",onClick:a,autoFocus:!0,children:"Restore"})]}),children:[$e("p",{children:["Saved ",Px(t),", with your bindings and scene settings."]}),pe("ul",{className:"bb-modelList","aria-label":"Saved models",children:e.map((o,n)=>$e("li",{className:"bb-modelRow",children:[pe(wx,{size:14,className:"bb-modelRowIcon","aria-hidden":"true"}),$e("span",{className:"bb-modelRowText",children:[pe("span",{className:"bb-modelRowName",title:o.name,children:o.name}),o.mergedCount>0?$e("small",{children:[o.mergedCount," merged ",o.mergedCount===1?"model":"models"]}):null]})]},n))})]})}function du({nodeLabel:e,count:t=1,onCancel:i,onConfirm:a}){let o=t>1;return $e(vn,{title:o?`Delete ${e}?`:"Delete this object?",icon:ds,onCancel:i,footer:$e(ui,{children:[pe(Ft,{onClick:i,children:"Cancel"}),pe(Ft,{variant:"danger",onClick:a,autoFocus:!0,children:"Delete"})]}),children:[o?null:pe("p",{children:pe("strong",{children:e})}),$e("p",{children:[o?"They leave":"It leaves"," the Outliner and the 3D view for every viewer, rather than being hidden as the Visible checkbox does. You can undo this."]})]})}function cu({destinations:e,onCancel:t,onChoose:i}){let[a,o]=Mx(e.find(s=>s.isActive)?.url??e[0]?.url??""),n=e.find(s=>s.url===a),d=au();return $e(vn,{title:"Add model",icon:pe(Cx,{size:15,"aria-hidden":"true"}),onCancel:t,footer:$e(ui,{children:[pe(Ft,{onClick:t,children:"Cancel"}),pe(Ft,{onClick:()=>i({mode:"separate"}),children:"Add as separate model"}),pe(Ft,{variant:"primary",disabled:!n,title:n?`Merge into ${n.name}`:void 0,onClick:()=>n&&i({mode:"merge",targetUrl:a}),children:"Merge into model"})]}),children:[pe("p",{children:"A separate model stays independent and has its own group in the Outliner. Merging adds its objects to the model you choose."}),pe("label",{htmlFor:d,children:"Merge into"}),pe("select",{id:d,value:a,onChange:s=>o(s.target.value),children:e.map(s=>$e("option",{value:s.url,children:[s.label,": ",s.name,s.isActive?" (active)":""]},s.url))})]})}function pu({options:e,onCancel:t,onRemoveModel:i,onRemoveMerge:a,onRemoveAll:o,permanent:n=!1}){let d=au();return $e(vn,{title:"Remove model",icon:ds,onCancel:t,footer:$e(ui,{children:[pe(Ft,{onClick:t,children:"Cancel"}),o?pe(Ft,{variant:"danger","aria-describedby":d,onClick:o,children:"Remove all models"}):null]}),children:[pe("p",{children:"Its bindings, transforms and anything merged into it go with it. The other models stay."}),pe("ul",{className:"bb-modelList","aria-label":"Models",children:e.map(s=>$e("li",{className:"bb-modelRow",children:[$e("span",{className:"bb-modelRowText",children:[pe("span",{className:"bb-modelRowName",title:s.label,children:s.label}),s.kind!=="model"?$e("small",{children:["Merged into ",s.ownerLabel]}):s.name!==s.label?pe("small",{title:s.name,children:s.name}):null]}),s.kind==="model"&&s.isActive?pe("span",{className:"bb-modelRowBadge",children:"Active"}):null,$e("button",{type:"button",className:"bb-removeRowButton","aria-label":`Remove ${s.label}`,onClick:()=>s.kind==="model"?i(s.url):a(s.url),children:[pe(kx,{size:13,"aria-hidden":"true"}),"Remove"]})]},s.url))}),pe("p",{id:d,children:n?"Removing a model removes it for everyone in this project and deletes its stored file unless another project uses it. You can't undo this.":"Removing all models also clears the session saved in this browser. You can't undo this, so export anything you want to keep first."})]})}import{strToU8 as Bx}from"fflate";function Tx(e){return(e.decals??[]).map(t=>t.image).filter(t=>!!t?.trim())}function Rx(e){let t=e.style?.material;return t?Object.values(t).filter(i=>!!i&&typeof i=="object"&&typeof i.path=="string"&&i.path.trim().length>0).map(i=>i.path):[]}async function uu(e){let t=new Set;for(let i of Object.values(e)){for(let a of Rx(i))t.add(a);for(let a of Tx(i))t.add(a)}return gu(t)}async function bu(e){let t=new Set,i=e.background?.imageUrl?.trim();return i&&t.add(i),gu(t)}async function gu(e){let t=[],i=[];return await Promise.all(Array.from(e).map(async a=>{let o=$t(a);if(o)try{let n=await fetch(o);if(!n.ok)throw new Error(String(n.status));t.push({path:a,blob:await n.blob()});return}catch{i.push(a);return}try{let n=await oo(a);n&&t.push({path:a,blob:n})}catch{}})),{assets:t,failedPaths:i}}async function bi(e,t,i,a,o){if(o.length===0){ip(e,t,i);return}let n={[e]:Bx(t)};for(let s of o)n[s.path]=new Uint8Array(await s.blob.arrayBuffer());let d=await Ji(n);fn(new Blob([d],{type:"application/zip"}),a)}async function hr(e){let t=e.background?.imageUrl?.trim();if(t)try{let i=await oo(t);i&&It(t,URL.createObjectURL(i))}catch(i){console.warn("[BindingBuilder] Could not rehydrate the background image:",i)}}async function Qo(e){return await Promise.all(Object.entries(e).map(async([t,i])=>{for(let o of i.decals??[])if(o.image)try{let n=await oo(o.image);n&&It(o.image,URL.createObjectURL(n))}catch(n){console.warn(`[BindingBuilder] Could not rehydrate a decal image on "${t}":`,n)}let a=i.style?.material;if(a)for(let o of Kl){let d=a[o]?.path;if(d)try{let s=await oo(d);if(!s){console.warn(`[BindingBuilder] No stored texture found for "${t}"'s ${o} ("${d}"). If this is meant to be an uploaded file rather than a hosted URL, it was uploaded before texture autosave existed (or this browser's storage was cleared) \u2014 re-upload it once so it's stored for future restores.`);continue}let p=URL.createObjectURL(s);It(d,p)}catch(s){console.warn(`[BindingBuilder] Could not rehydrate "${t}"'s ${o}:`,s)}}})),e}async function gi(e){if(!e)return;let t={};for(let i of e.definition.groups)for(let a of i.options)for(let[o,n]of(a.appearance??[]).entries())if(n.material){let d=JSON.stringify([i.id,a.id,o]);t[d]={id:d,modelObjectId:d,style:{material:n.material}}}await Qo(t)}async function mu(e){let t=new Set,i=new WeakSet;function a(o,n=0){if(!(!o||typeof o!="object"||i.has(o)||n>64)){i.add(o);for(let[d,s]of Object.entries(o))d!=="metadata"&&(d==="path"&&typeof s=="string"&&s?t.add(s):a(s,n+1))}}return a(e),await Promise.all([...t].map(async o=>{let n=await oo(o);n&&It(o,URL.createObjectURL(n))})),e}function fu({bindings:e,setBindings:t,sceneConfig:i,setSceneConfig:a,nodeKeys:o,sceneConfigInputRef:n,setIsExporting:d,setStatusMessage:s,setStatusTone:p}){let c=f=>h("bindings",()=>uu(e),u=>f==="json"?bi("objectBindings.json",ri(e),"application/json","objectBindings.zip",u):bi("objectBindings.ts",cr(e),"text/typescript","objectBindings-ts.zip",u)),x=f=>h("scene config",()=>bu(i),u=>f==="json"?bi("sceneConfig.json",pr(i),"application/json","sceneConfig.zip",u):bi("sceneConfig.ts",ur(i),"text/typescript","sceneConfig-ts.zip",u)),h=async(f,u,v)=>{d(!0);try{let{assets:m,failedPaths:N}=await u();await v(m),N.length>0?(s(`Exported, but ${N.length} uploaded image${N.length===1?"":"s"} couldn't be bundled: ${N.join(", ")}.`),p("error")):m.length>0&&(s(`Exported with ${m.length} uploaded image${m.length===1?"":"s"} bundled into the zip.`),p("success"))}catch(m){let N=m instanceof Error?m.message:"Unknown export error.";s(`Failed to export ${f}: ${N}`),p("error")}finally{d(!1)}},g=async f=>{if(!o.length){s("Load a model before importing bindings."),p("error");return}let u;try{u=JSON.parse(await f.text())}catch{s(`${f.name} is not valid JSON.`),p("error");return}if(u===null||typeof u!="object"||Array.isArray(u)){s("Expected a JSON object mapping object IDs to bindings."),p("error");return}let v=new Map;for(let P of Object.values(u))if(P!==null&&typeof P=="object"&&typeof P.id=="string"&&typeof P.type=="string"&&typeof P.modelObjectId=="string"){let $=P;v.set($.modelObjectId,$)}if(v.size===0){s(`${f.name} doesn't look like an exported bindings file.`),p("error");return}let m={...e},N={},A=0;for(let P of Object.keys(m)){let $=v.get(P);$&&(m[P]=$,N[P]=$,A++)}if(A===0){s(`None of the object IDs in ${f.name} match this model \u2014 nothing imported.`),p("error");return}let G=await Qo(N);Object.assign(m,G),t(m);let B=v.size-A;s(B>0?`Imported ${A} binding${A===1?"":"s"} from ${f.name} (${B} skipped \u2014 not in this model).`:`Imported ${A} binding${A===1?"":"s"} from ${f.name}.`),p("success")},C=async f=>{let u=f.target.files?.[0];u&&(await g(u),f.target.value="")},M=()=>{n.current?.click()},y=async f=>{let u;try{u=JSON.parse(await f.text())}catch{s(`${f.name} is not valid JSON.`),p("error");return}if(u===null||typeof u!="object"||Array.isArray(u)){s("Expected a JSON object with scene config sections."),p("error");return}let v=["model","camera","lighting","wireframe","shadows","environment","background","groundShadows","postProcessing","animations","annotations","cinematic","styleRules","section","measurements","selectionSets","product"],m=u;if(m.product!==void 0)try{m.product=Gi(m.product)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(m.section!==void 0)try{m.section=Vi(i.section,m.section)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(m.selectionSets!==void 0)try{m.selectionSets=mn(m.selectionSets)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(m.measurements!==void 0)try{m.measurements=Ki(m.measurements)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}let N=v.filter(A=>m[A]!==void 0);if(N.length===0){s(`${f.name} doesn't look like an exported scene config file.`),p("error");return}await gi(m.product),N.includes("background")&&m.background&&await hr({background:m.background}),a(A=>{let G={...A};for(let B of N)G[B]=B==="measurements"||B==="section"||B==="product"?m[B]:ei(A[B],m[B]);return G}),s(`Imported ${N.length} section${N.length===1?"":"s"} from ${f.name}.`),p("success")};return{handleExportBindings:c,handleExportSceneConfig:x,importBindingsFile:g,handleImportBindingsChange:C,openSceneConfigImportPicker:M,importSceneConfigFile:y,handleImportSceneConfigChange:async f=>{let u=f.target.files?.[0];u&&(await y(u),f.target.value="")}}}var cs={pbr:["texture","baseColor","metalness","metalnessMap","specularIntensity","specularIntensityMap","specularColor","specularColorMap","reflectivity"],roughness:["roughness","roughnessMap"],emission:["emissive","emissiveIntensity","emissiveMap"],opacity:["opacity","alphaMap","alphaTest","alphaHash","dithering","blendingMode"],normalBump:["normalMap","normalScale","flipNormalY","bumpMap","bumpScale"],displacement:["displacementMap","displacementScale","displacementBias"],ao:["aoMap","aoMapIntensity"],clearcoat:["clearcoat","clearcoatMap","clearcoatRoughness","clearcoatRoughnessMap","clearcoatNormalMap","clearcoatNormalScale","flipClearcoatNormalY"],sheen:["sheen","sheenColor","sheenColorMap","sheenRoughness","sheenRoughnessMap"],anisotropy:["anisotropy","anisotropyRotation","anisotropyMap"],transmission:["transmission","transmissionMap","thickness","thicknessMap","attenuationColor","attenuationDistance"],faces:["side"]},hu=Object.keys(cs);function xu(e){if(e==null)return!1;if(typeof e=="string")return e.trim().length>0;if(typeof e=="number")return Number.isFinite(e);if(typeof e=="boolean")return e;if(typeof e=="object"&&"path"in e){let t=e.path;return typeof t=="string"&&t.trim().length>0}return!1}function ps(e){if(e)return Object.values(e).some(xu)?e:void 0}function Bt(e,t){return e?cs[t].some(i=>xu(e[i])):!1}function us(e){return{pbr:Bt(e,"pbr"),roughness:Bt(e,"roughness"),emission:Bt(e,"emission"),opacity:Bt(e,"opacity"),normalBump:Bt(e,"normalBump"),displacement:Bt(e,"displacement"),ao:Bt(e,"ao"),clearcoat:Bt(e,"clearcoat"),sheen:Bt(e,"sheen"),anisotropy:Bt(e,"anisotropy"),transmission:Bt(e,"transmission"),faces:Bt(e,"faces")}}function bs(e,t){if(t)return{...e,style:{...e.style,material:t}};if(!e.style)return e;let{material:i,...a}=e.style;return{...e,style:Object.keys(a).length>0?a:void 0}}function vu(e,t){if(!e)return;let i={...e};for(let a of cs[t])delete i[a];return i}import{ChevronDown as Nx,ChevronUp as Ax}from"lucide-react";import{jsx as en,jsxs as yu}from"react/jsx-runtime";function wu({panel:e,tabs:t,tab:i,onTabChange:a,hasModel:o,onPointerDownCapture:n,children:d}){let s=e.open&&o;return yu("div",{className:`bb-dock ${s?"bb-dock--open":""}`,onPointerDownCapture:n,children:[s?en(ii,{orientation:"horizontal",label:"Resize timeline",onPointerDown:e.startResize,onKeyDown:e.onResizeKey}):null,yu("div",{className:"bb-tabs bb-dockBar",role:"tablist","aria-label":"Animation",children:[t.map(({id:p,label:c})=>en("button",{type:"button",role:"tab",disabled:!o,"aria-selected":e.open&&i===p,className:`bb-tab ${e.open&&i===p?"bb-tab--active":""}`,onClick:()=>{e.open&&i===p?e.setOpen(!1):(a(p),e.setOpen(!0))},children:c},p)),en("span",{className:"bb-topBarSpacer"}),en("button",{type:"button",className:"bb-toolButton bb-toolButton--small",disabled:!o,"aria-label":e.open?"Collapse timeline":"Expand timeline",onClick:()=>e.setOpen(!e.open),children:e.open?en(Nx,{size:14}):en(Ax,{size:14})})]}),s?en("div",{className:"bb-dockBody",style:{height:e.size},children:d}):null]})}import{Fragment as et,jsx as R,jsxs as ae}from"react/jsx-runtime";var Gx=ko(()=>import("./AnnotationsTab-OHRVWRKI.mjs")),qx=ko(()=>import("./AnimationsTab-NUJTEMZ5.mjs")),Wx=ko(()=>import("./SequencesTab-JTIVIZJD.mjs")),Yx=ko(()=>import("./CinematicTab-IJAY2BS6.mjs")),Jx=ko(()=>import("./ConfigureTab-UQRRATCY.mjs")),ku="/room.glb";function gs(){return`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function ms(e){return`Couldn't reload ${e} from your last session. It's still saved in this browser.`}function Xx({label:e,values:t,onChange:i}){let a=t.length>0&&t.every(Boolean),o=!a&&t.some(Boolean);return ae("label",{className:"bb-groupFlag",children:[R("input",{type:"checkbox",ref:n=>{n&&(n.indeterminate=o)},checked:a,onChange:n=>i(n.target.checked)}),e]})}var Zx=[{id:"outliner",label:"Outliner"},{id:"assets",label:"Assets"},{id:"annotations",label:"Annotations"},{id:"measure",label:"Measure"}],Qx=[{id:"sequences",label:"Sequences"},{id:"clips",label:"Clips"},{id:"cinematic",label:"Cinematic"}],Cu=[{id:"general",label:"General",group:!0},{id:"material",label:"Material",group:!0},{id:"decals",label:"Decals",group:!1},{id:"actions",label:"Actions",group:!1},{id:"data",label:"Data",group:!0}],Mu={bindings:"object",scene:"scene",assets:"asset"},ev=ae(et,{children:[R("kbd",{children:"G"})," Move ",R("kbd",{children:"R"})," Rotate ",R("kbd",{children:"T"})," Scale ",R("kbd",{children:"F"})," Frame"," ",R("kbd",{children:"?"})," Shortcuts"]});function Pu(e,t=!1){let i=e;return i?.tagName?i.isContentEditable||i.tagName==="TEXTAREA"||t&&i.tagName==="SELECT"?!0:i.tagName!=="INPUT"?!1:!["range","checkbox","radio","button","file","color"].includes(i.type):!1}function tv({topBarStart:e,configurePublish:t,licenseKey:i,licenseValidationUrl:a,arHandoff:o=!0,mobileHandoffUrl:n,dracoDecoderPath:d,ktx2TranscoderPath:s,meshopt:p,project:c,onProjectChange:x,projectChangeDebounceMs:h=350,onModelUpload:g,onTextureUpload:C,onThumbnailCapture:M,hasThumbnail:y=!1,onEditLeaseChange:T,allowModelChange:f=!0,hideLicenseCheckingOverlay:u=!1}){let v=ne(null),m=ne(null),N=ne(null),A=ne(null),G=ne(null),[B]=U(()=>c?wa(c):null),[P,$]=U(B?.url??null),[H,de]=U(()=>c?c.models.filter(r=>r!==B).map(ka):[]),[_,Q]=U(()=>c?c.models.map(r=>r.url):[]),[w,I]=U(B?.name??""),[he,Ne]=U(B),j=Ue(()=>c&&_.length>1&&he?.tilesetUrl?{...he,tilesetUrl:null}:he,[c,_.length,he]),J=ne(c?Ca(c):new Map),{selectedItem:L,setSelectedItem:Ce,multiSelectMode:tn,setMultiSelectMode:Bu,multiSelectedKeys:_e,setMultiSelectedKeys:xr,groupSelectionActive:Oe,selectObject:En,setSelection:fs,toggleMultiSelect:Tu,exitMultiSelect:hs,clearSelection:xs}=Qp(),vs=ne({mode:!1,keys:[]}),mi=ne({shiftKey:!1,ctrlKey:!1,metaKey:!1}),[jn,Ru]=U(null);vs.current={mode:Oe,keys:_e};let ie=Gp(B?.objectBindings??{}),q=ie.value,To=ie.setValue,fi=ne("free");Zp({bindings:q,multiSelectMode:Oe,selectedItem:L,multiSelectedKeys:_e,setSelectedItem:Ce,setMultiSelectedKeys:xr});let Ee=ie.mergeSources,so=ie.setMergeSourcesUntracked;ze(()=>{B?.mergeModels?.length&&so(Sn(B))},[B,so]);let[Me,qt]=U(!1),[hi,In]=U(null),Nu=Ue(()=>hi?{target:hi}:null,[hi]);ze(()=>{In(null)},[P]),ze(()=>{Bu(!1),xr([])},[P]);let[xi,lo]=U(null);ze(()=>lo(null),[L,P]),ze(()=>{Dr(null),Hr(null)},[P]);let[Au,Ro]=U(null),[ys,Ou]=U(!1),[vr,W]=U(""),[yr,X]=U("default"),[Eu,ws]=U(null),ju=Z(()=>ws(null),[]),[Ss,vi]=U("{}"),[ks,yi]=U("{}"),[Iu,wi]=U(null),[zu,Si]=U(null),[Lu,zn]=U(!1),co=dr("left",{size:296,min:220,max:480,edge:"right"}),Wt=dr("inspector",{size:320,min:300,max:560,edge:"left"}),wr=dr("dock",{size:300,min:160,max:640,edge:"top",open:!1}),[Tt,Sr]=U("outliner"),[ki,Cs]=U("sequences"),[Ms,Ps]=U("general"),[Bs,kr]=U(!1),[Cr,Du]=U(!0),[Fu,Mr]=U(!1),[Hu,Pr]=U(!1),[Ln,No]=U("bindings"),[Yt,Ts]=U({identity:!0,basics:!0,material:!0,decals:!0,actions:!0,camera:!1,transform:!0,metrics:!0,metadata:!0}),[$u,Uu]=U({pbr:!0,roughness:!0,emission:!1,opacity:!0,normalBump:!1,displacement:!1,ao:!1,clearcoat:!1,sheen:!1,anisotropy:!1,transmission:!1,faces:!1}),Jt=r=>Ts(l=>({...l,[r]:!l[r]})),_u=r=>Uu(l=>({...l,[r]:!l[r]})),[Ci,Rs]=U(null),[po,Br]=U(!1),[ht,on]=U("object"),[nn,Tr]=U("model"),[Ns,As]=U(null),[Os,Es]=U(!1),[js,Vu]=U(null),Is=co.setOpen,zs=Z(()=>{Is(!0),Sr("measure"),Es(!0)},[Is]),[Ku,Gu]=U("metalness"),[qu,Rr]=U(us()),Ls=ne(null),[Ds,Wu]=U(!1),[Nr,Yu]=U(!0),[Ar,Ju]=U(!0),[Xu,Fs]=U(!1),[Dn,Hs]=U(null),[Ao,Or]=U(null),[Zu,Er]=U(!1),Mi=ne(null),Pi=ne({modelUrl:P,modelName:w,modelOrder:_,parkedModels:H});Pi.current={modelUrl:P,modelName:w,modelOrder:_,parkedModels:H};let[Qu,rn]=U(!1),[uo,jr]=U(null),[Xt,Bi]=U("select"),eb=Xt==="move"||Xt==="rotate",tb=Xt==="scale",[$s,ob]=U("world"),xt=ne({}),Be=ti(c&&B?er(c.sceneConfig,B):fo),Ve=ti(c?Sa(c):Do),[Us,an]=U([]),rt=Ue(()=>({...Ve.value,placements:{...Object.fromEntries(Us.map(r=>[r,{deleted:!0}])),...Ve.value.placements}}),[Ve.value,Us]),[sn,ln]=U(!1),_s=ne(null),ee=Be.value,Rt=Be.setValue,nb=Z(r=>{let l=mn(r);Be.setValueAsStep(b=>({...b,selectionSets:l}))},[Be.setValueAsStep]),Ti=Be.setValueUntracked,Ir=Z(r=>{let l=Xe(ee,r.modelSettings);r.sceneHistory?Be.restoreSnapshot({...r.sceneHistory,present:l}):Be.reset(l)},[ee,Be.restoreSnapshot,Be.reset]),{hasEdits:ib,markSessionEdited:at,resetSessionEdits:zr}=tu(ie.edits,Be.edits+Ve.edits),[Oo,Vs]=U(!1),[rb,ab]=U(.5),[Lr,sb]=U(!0),[dn,Dr]=U(null),cn=dn??{bindings:ie.baseline,sceneConfig:Be.baseline},[Fr,lb]=U("modelObjectId"),[Ri,Hr]=U(null),Fn=Ue(()=>Oo?fd({objectBindings:cn.bindings,sceneConfig:cn.sceneConfig},{objectBindings:q,sceneConfig:ee},{matchBy:Fr}):null,[Oo,cn.bindings,cn.sceneConfig,q,ee,Fr]),Ks=Ue(()=>Fn&&Lr?{before:ga(Fn,"before",Ri),after:ga(Fn,"after",Ri)}:null,[Fn,Ri,Lr]),[Gs,$r]=U("orbit"),[db,qs]=U(!1),Ur=ne(void 0),_r=Z(()=>{qs(!0),clearTimeout(Ur.current),Ur.current=setTimeout(()=>qs(!1),5e3)},[]);ze(()=>()=>clearTimeout(Ur.current),[]),ze(()=>{P&&!Me&&_r()},[P,Me,_r]);let Ge=Gs==="pointerLock",[Ws,cb]=U(null),Ys=ne(null),pb=Ws?.objectKey===L&&Ws?.textureKey==="texture",[ub,pn]=U(null),[bb,Vr]=U(null),Hn=nd(i,a),Eo=ed(Hn.tier);fi.current=Eo;let Js=td.models[Eo],gb=Ue(()=>({isInsideEditor:!0,activeTab:ht,activeSubTab:nn,tier:Eo,setActiveTab:on,setActiveSubTab:Tr,measurementPanelTarget:Ns,setMeasurementPanelTarget:As,measurementsPanelOpen:Os,setMeasurementsPanelOpen:Es,openMeasurementsPanel:zs,xrToolsTarget:js,annotating:Tt==="annotations"}),[ht,nn,Eo,Ns,Os,zs,js,Tt]),Je=ne(null),un=ne(0),vt=ne(0),Xs=ne(c?`${c.id}:${c.revision}`:null),Zs=ne(null),ov=ne(!1),Ni=ne(!1),Ai=ne(c?kn(c):null),Kr=ne(!1),Oi=ne(new Set),Ei=ne(new Map),ji=ne(void 0),bo=ne(0),mb=Xl(Au,bo.current===100),Le=ne(null),tt=ne(c?{requestId:0,modelName:B.name??"model",modelUrl:B.url,storedBindings:B.objectBindings,streaming:!!B.tilesetUrl}:null),qe=ne(B?{model:{kind:"url",url:B.url,name:B.name??"model"}}:null),Ii=ne(new Set),Zt=ne(new Map);Wp(ie.snapshot,H,{modelUrl:P,modelSourceRef:qe,uploadedFilesRef:Zt});let $n=ne(null),fb=ne(!1),Qt=ne(null),yt=ne(new Map),[Gr,Qs]=U(0),go=Ue(()=>new Map(_.map(r=>{let l=r===P?qe.current?.model:H.find(b=>b.url===r)?.sessionModel;return[r,l?Ut(l):`url:${r}`]})),[_,P,H]),Un=r=>rt.placements[go.get(r)??`url:${r}`]??{},me=Ue(()=>_.map((r,l)=>({id:go.get(r)??`url:${r}`,url:r,name:Un(r).label??(r===P?w:H.find(b=>b.url===r)?.name)??`Asset ${l+1}`,placement:Un(r),ready:yt.current.has(r)})).filter(r=>!r.placement.deleted),[_,P,w,H,rt,go,Gr]),el=St(Eo,"models",me.length),eo=Ue(()=>{let r=Hp(me.map(l=>l.name));return new Map(me.map((l,b)=>[l.url,r[b]]))},[me]),[qr,hb]=U(!1),[tl,ol]=U(null),[xb,nl]=U(null),vb=Z(()=>{let r=P?yt.current.get(P):void 0;!r||!P||ol({url:P,report:ql(r,{source:{...Gl(r),name:w},scope:j?.tilesetUrl?"resident-tiles":"asset"})})},[P,w,j?.tilesetUrl]);ze(()=>{nl(null)},[P,qr]);let{materialVariantGroups:il,objectsWithoutUvs:rl,hierarchy:yb}=ru({modelUrl:P,scenesRef:yt,sceneRevision:Gr,streaming:!!j?.tilesetUrl});ze(()=>{let r=new Set(me.map(l=>l.url));for(let l of yt.current.keys())r.has(l)||yt.current.delete(l)},[me]),iu({enabled:!j?.tilesetUrl,modelUrl:P,bindings:q,mergeSources:Ee,parkedModels:H,scenesRef:yt,sceneRevision:Gr,setBindings:ie.setValueUntracked,setParkedModels:de});let jo=ne(null),[wb,Sb]=U(null),[al,kb]=U({}),Cb=Ue(()=>{if(!Oe||_e.length===0||!jo.current)return null;let l=_e.filter(b=>q[b]&&!q[b].removed).map(b=>al[b]).filter(b=>!!b);return l.length>0?l:null},[Oe,_e,al,q]),{cameraState:Pe,resetView:sl,focusObject:_n,fitScene:ll,setCameraState:zi,handleCameraChange:dl,handleViewerReady:Mb}=Rl(),{markThumbnailOutdated:Pb,noteThumbnailActivity:cl}=Xp({onCapture:M,hasThumbnail:y,viewerRef:jo,isModelLoading:()=>!P||!!tt.current}),Bb=Z((...r)=>{cl(),dl(...r)},[dl,cl]),pl=Z(r=>{Ge||zi({position:r.position,target:r.target,fov:r.fov??Pe?.fov??null,zoom:r.zoom??Pe?.zoom??1,azimuthAngle:r.azimuthAngle,polarAngle:r.polarAngle},!0)},[Ge,zi,Pe]),Nt=vd(),Tb=Ue(()=>me.map(r=>r.url),[me]),At=rc(Tb),Li=sc({modelUrl:P,sceneConfig:ee,setSceneConfig:Rt,setSceneConfigUntracked:Ti,parkedModels:H,setParkedModels:de,animations:At,markSessionEdited:at}),ul=ht==="configure"&&!po&&Ci&&ee.product,Rb=Ue(()=>ul&&ee.product?{...ee,product:{...ee.product,selections:Ci}}:ee,[ul,ee,Ci]),Nb=Z(r=>Rt(l=>({...r,product:l.product})),[Rt]);ze(()=>{ht!=="configure"&&Rs(null)},[ht]),ze(()=>{if(!po)return;let r=l=>{l.key==="Escape"&&Br(!1)};return window.addEventListener("keydown",r),()=>window.removeEventListener("keydown",r)},[po]);let Se=L?q[L]??null:null,Wr=Se?.style?.material,bl=!rl.has(Se?.modelObjectId??L??""),Ab=Ue(()=>{if(!(me.length<2))return me.map(r=>({url:r.url,label:eo.get(r.url)??r.name,bindings:r.url===P?q:H.find(l=>l.url===r.url)?.bindings??{},isActive:r.url===P}))},[me,eo,P,q,H]),Vn=Ue(()=>{let r=[];return me.forEach((l,b)=>{let S=l.url,k=S===P,E=k?void 0:H.find(K=>K.url===S),D=eo.get(S)||l.name||`Asset ${b+1}`;r.push({kind:"model",url:S,label:D,name:k?w:E?.name??"Untitled model",isActive:k}),(k?Ee:E?.mergedModelSources??[]).forEach(K=>{r.push({kind:"merge",url:K.url,label:"Merged nodes",name:Gt(K.namePrefix),ownerLabel:D})})}),c&&me.length<2?r.filter(l=>l.kind!=="model"):r},[c,me,P,w,H,Ee]),Yr=Ue(()=>Ee.map(r=>({url:r.url,namePrefix:r.namePrefix})),[Ee]),Ob=Ue(()=>(c?_.length<2:_.length<1)?void 0:_.map((l,b)=>{let S=rt.placements[go.get(l)??`url:${l}`]??{},k={transform:S,visible:S.visible!==!1&&!S.deleted,label:S.label};if(l===P)return{url:l,label:eo.get(l)??k.label??(w||`Model ${b+1}`),transform:k.transform,visible:k.visible,objectBindings:q,originalNodePoses:xt.current,mergeModels:Yr};let D=H.find(F=>F.url===l);return{url:l,label:eo.get(l)??k.label??(D?.name||`Model ${b+1}`),transform:k.transform,visible:k.visible,objectBindings:D?.bindings??{},originalNodePoses:D?.originalTransforms,sceneConfig:Xe(ee,D?.modelSettings),mergeModels:(D?.mergedModelSources??[]).map(F=>({url:F.url,namePrefix:F.namePrefix}))}}).filter(l=>!rt.placements[go.get(l.url)??`url:${l.url}`]?.deleted),[c,_,P,w,q,H,Yr,ee,rt,go,eo]);ze(()=>{let r=N.current;if(r)return r.style.setProperty("--bb-canvas-hint-top",Oo?"48px":"12px"),()=>{r.style.removeProperty("--bb-canvas-hint-top")}},[Oo]);let mo=Se?.cameraState,Eb=Pe?{position:Ia(Pe.position),target:Ia(Pe.target)}:null,jb=Z(r=>{Rt(l=>{let b=l.annotations.map(k=>k.id).join(","),S=r.map(k=>k.id).join(",");return b===S?l:r.length>l.annotations.length&&!St(fi.current,"annotations",l.annotations.length)?(W(`More annotations require the ${ua[Ho("annotations",l.annotations.length)]} plan or higher.`),X("error"),l):{...l,annotations:r}})},[]),Ib=Z(r=>{pn(r?{annotation:r}:null)},[]);ze(()=>{if(!Se){vi("{}"),yi("{}"),wi(null),Si(null);return}vi(ja(Se.metrics)),yi(ja(Se.metadata)),wi(null),Si(null)},[Se]),ze(()=>{let r=us(Wr);if(Ls.current!==L){Ls.current=L,Rr(r);return}Rr(l=>{let b=!1,S={...l};for(let k of hu)r[k]&&!l[k]&&(S[k]=!0,b=!0);return b?S:l})},[L,Wr]),ze(()=>()=>{Je.current?.cleanup(),Le.current&&clearTimeout(Le.current)},[]);let Di=Z((r,l)=>{let b=Yn(r);if(l){let S=new Map(Object.values(l).map(k=>[k.modelObjectId,k]));for(let k of r){let E=S.get(k);E&&(b[k]=E)}}return b},[]);ze(()=>{if(!c)return;let r=`${c.id}:${c.revision}`;if(Xs.current===r)return;Xs.current=r,J.current=Ca(c);let l=c.models.find(te=>te.url===P),b=l&&!c.composition.placements[Vo(l.url)]?.deleted?l:wa(c),S=er(c.sceneConfig,b),k=P!==b.url||he?.tilesetUrl!==b.tilesetUrl||he?.assetVersion!==b.assetVersion,E=kn(c);if(!k&&Oi.current.delete(E)){Ai.current=E;return}Oi.current.clear();let D=!tr(q,b.objectBindings),F=!tr(ee,S);Ne(b),I(b.name??"model");let K=b.objectBindings;if(D){let te=Zs.current;K=te?Di(te,b.objectBindings):b.objectBindings,ie.reset(K)}else K=q;F&&Be.reset(S),de(te=>c.models.filter(ke=>ke.url!==b.url).map(ke=>{let ct=te.find(Ot=>Ot.url===ke.url);if(!ct)return ka(ke);let we=JSON.stringify(ct.mergedModelSources.map(Ot=>Ot.url))===JSON.stringify((ke.mergeModels??[]).map(Ot=>Ot.url));return{...ct,name:ke.name??ct.name,bindings:ke.objectBindings,modelSettings:ke.modelSettings,mergedModelSources:we?ct.mergedModelSources:Sn(ke),bindingHistory:we?ct.bindingHistory:void 0}})),Q(c.models.map(te=>te.url));let le=(b.mergeModels??[]).map(te=>te.url);if(JSON.stringify(Ee.map(te=>te.url))!==JSON.stringify(le)&&(so(Sn(b)),ie.clearHistory()),tr(Ve.value,c.composition)||Ve.reset(Sa(c)),k){Nt.clearAnimations();let te=++vt.current;tt.current={requestId:te,modelName:b.name??"model",modelUrl:b.url,storedBindings:b.objectBindings,streaming:!!b.tilesetUrl},qe.current={model:{kind:"url",url:b.url,name:b.name??"model"}},Qt.current=null,Ce(null),qt(!0),$(b.url)}Ai.current=kn({models:c.models.map(te=>te===b?{...te,objectBindings:K}:te),composition:c.composition,sceneConfig:c.sceneConfig})},[he,q,Di,Ve,Ee,c,P,ee,ie,Be,so,Nt.clearAnimations]);let Jr=ne(x);Jr.current=x;let gl=ne(C);gl.current=C,ze(()=>{if(!c||!Jr.current||!P||tt.current)return;let r=()=>Ud({project:c,modelUrl:P,modelName:w,bindings:q,sceneConfig:ee,mergedModelSources:Ee,parkedModels:H,modelOrder:_,composition:rt,sources:J.current});Ni.current&&(Ni.current=!1,Ai.current=kn({...r(),composition:c.composition,sceneConfig:c.sceneConfig}));let l=window.setTimeout(()=>{if(Kr.current)return;let b=r(),S=kn(b);if(S===Ai.current||Oi.current.has(S))return;let k=gl.current,E=k?_o(b.models).size+_o(b.sceneConfig).size:0;if(k&&E>0){Kr.current=!0;let D=_o(b.sceneConfig,_o(b.models));Promise.all([...D].map(async F=>{if(!Ei.current.has(F))try{Ei.current.set(F,await k(await Vd(F),F))}catch(K){W(K instanceof Error?K.message:"Could not save an image."),X("error"),Ei.current.set(F,"")}})).then(()=>{Kr.current=!1;let F=K=>Qi(K,Ei.current);ie.setValueUntracked(F),Be.setValueUntracked(F),de(K=>K.map(le=>({...le,bindings:F(le.bindings),modelSettings:F(le.modelSettings)})))});return}Oi.current.add(S),Jr.current?.(b,"local"),Pb()},h);return()=>window.clearTimeout(l)},[q,rt,Ee,w,_,P,H,c,h,ee]);let Io=Ln==="assets"?Ve:Ln==="scene"?Be:ie;ze(()=>{let r=l=>{l.key.toLowerCase()!=="z"||!(l.metaKey||l.ctrlKey)||Pu(l.target)||(l.preventDefault(),l.shiftKey?Io.redo():Io.undo())};return window.addEventListener("keydown",r),()=>window.removeEventListener("keydown",r)},[Io]);let Fi=!c&&f,{handleTextureUpload:zb}=Yp({composition:rt,autosaveEnabled:Fi,hasEdits:ib,modelUrl:P,bindings:q,sceneConfig:ee,parkedModels:H,mergedModelSources:Ee,modelOrder:_,onTextureUpload:C,modelSourceRef:qe,pendingLoadRef:tt,storedModelKeysRef:Ii,uploadedFilesRef:Zt,pendingAutosaveRef:$n,autosaveFailureShownRef:fb,setStatusMessage:W,setStatusTone:X});ze(()=>{Me||yr==="default"||ws({id:Date.now(),text:vr,tone:yr})},[vr,yr,Me]);let Ht=Ue(()=>Object.keys(q),[q]),Lb=Ue(()=>!L||!Se?null:Se.id.trim()?Object.entries(q).some(([b,S])=>b!==L&&S.id===Se.id)?"Another binding already uses this ID.":null:"ID is required.",[q,L,Se]),wt=(r,l)=>{To(b=>{let S=vs.current,k=S.mode&&S.keys.includes(r)?S.keys.filter(D=>b[D]):[r];if(k.length<=1)return{...b,[r]:l(b[r],r)};let E={...b};for(let D of k){let F=b[D];E[D]={...l(F,D),id:F.id,modelObjectId:F.modelObjectId}}return E})},Xr=(r,l)=>{wt(r,b=>{let S=ps(l(b.style?.material));return bs(b,S)})},Db=(r,l,b)=>{Xr(r,S=>({...S,[l]:b?{path:b}:void 0}))},Fb=(r,l)=>{Rr(b=>({...b,[r]:l})),!l&&L&&wt(L,b=>{let S=ps(vu(b.style?.material,r));return bs(b,S)})},Zr=Z((r,l,b)=>{let{bindings:S,originalTransforms:k,nodeNames:E}=pi(r,b);xt.current=k,ie.reset(Xo(r,b??{},Ee,S)),Ce(E[0]??null),b||Ti(F=>({...F,annotations:[]})),W(`Generated ${E.length} bindings from ${l}.`),X("success"),Le.current&&clearTimeout(Le.current);let D=setTimeout(()=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{Le.current===D&&(bo.current=100,Ro(100),Le.current=setTimeout(()=>{Le.current=null,qt(!1),Ro(null)},400))})})},0);Le.current=D},[ie,Ti,Ee]),Qr=(r,l,b,S)=>{$n.current?.();let k=++vt.current;zr(),Ve.reset(Do),an([]),c||Be.reset(r!==P?Xe(ee):ee),r!==P&&Nt.clearAnimations(),H.forEach(F=>F.resolved?.cleanup()),de([]),Q([r]),so([]),qt(!0),Ro(null),bo.current=0,Le.current&&(clearTimeout(Le.current),Le.current=null),ji.current=b;let E=b?b/1048576:0;W(E>=100?`Reading the file. At ${Math.round(E)} MB, this can take a while.`:"Reading the file and generating bindings."),X("default"),I(l),Ne(S??{url:r,name:l}),pn(null);let D=Qt.current;if(r===P&&D?.url===r){tt.current=null,Zr(D.scene,l);return}tt.current={requestId:k,modelName:l,modelUrl:r,streaming:!!S?.tilesetUrl},$(r),ie.reset({}),Ce(null)},Hb=Z(r=>{P&&yt.current.get(P)!==r&&(yt.current.set(P,r),Qs(b=>b+1));let l=tt.current;if(!(l&&l.requestId!==vt.current)&&(P&&(Qt.current={url:P,scene:r}),lo(null),In(null),!!l)){if(tt.current=null,l.streaming){W(`Streaming ${l.modelName}.`),X("success"),qt(!1);return}l.storedBindings&&(Ni.current=!0),Zr(r,l.modelName,l.storedBindings),l.restoring&&W(`Restored your last session with ${l.modelName}.`)}},[Zr,P]),$b=Z(r=>{if(!j?.tilesetUrl)return;let l=r.map(k=>k.name);if(l.length===0)return;Zs.current=l,Ni.current=!0;let b=c?.models.find(k=>k.url===P)?.objectBindings,S=Di(l,b);ie.reset(S),Ce(k=>k??l[0]??null),W(`Streaming ${l.length} bindable objects.`),X("success"),qt(!1)},[Di,ie,P,c,j]),Ub=Z(r=>{let l=tt.current;if(!(l&&l.requestId!==vt.current)){if(tt.current=null,console.error(r),l?.restoring)qe.current=null,$(null),W(ms(l.modelName));else if(l)W(Wl(r)?`${l.modelName} is a point cloud: it has points but no faces. Turn it into a mesh first, for example with MeshLab or Blender.`:`Could not read ${l.modelName}. Make sure the file is a valid GLB, GLTF, OBJ, FBX, USDZ, STL, or PLY asset.`);else{let{detail:b}=qi(r,P??"",Je.current?.format);W(`Could not read ${w||"the model"}. ${b}`)}X("error"),Le.current&&(clearTimeout(Le.current),Le.current=null),bo.current=0,qt(!1),Ro(null)}},[P,w]),_b=Z(r=>{let l=null;if(r.lengthComputable&&r.total>0)l=r.loaded/r.total*100;else{let S=ji.current;S&&S>0&&(l=r.loaded/S*100)}if(l===null)return;let b=Math.min(99,Math.floor(l));b>bo.current&&(bo.current=b),Ro(S=>l>=99.5?100:Math.max(S??0,b)),l>=99.5&&W(S=>S.startsWith("Finalizing")?S:"Finalizing: parsing geometry and textures.")},[]),Vb=Z(r=>{Nt.handleAnimationsReady(r),P&&At.handleModelAnimationsReady(P,r)},[Nt,P,At.handleModelAnimationsReady]),nv=async()=>{Je.current?.cleanup(),Je.current=null,qe.current={model:{kind:"url",url:ku,name:"room.glb"}},await Qr(ku,"room.glb")},ml=async r=>{if(!f)return;if(r.name.toLowerCase().endsWith(".ri.zip")){await kl(r);return}if(g){try{qt(!0),W(`Uploading ${r.name}...`),X("default");let S=await g(r);J.current.set(S.url,S),qe.current={model:{kind:"url",url:S.url,name:S.name??r.name}},await Qr(S.url,S.name??r.name,r.size,S)}catch(S){qt(!1),W(S instanceof Error?S.message:`Could not upload ${r.name}.`),X("error")}return}let l;try{l=await ho(r)}catch(S){W(S instanceof Error?S.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, .stl, .ply, or .zip asset."),X("error");return}Je.current?.cleanup(),Je.current=l;let b=gs();Zt.current.set(b,r),qe.current={model:{kind:"file",key:b,name:l.name},file:r},await Qr(l.url,l.name,r.size,{url:l.url,name:l.name})},Kb=async r=>{let l=r.target.files?.[0];l&&(await ml(l),r.target.value="")},Hi=()=>{$n.current=null,at(),Je.current?.cleanup(),Je.current=null,Qt.current=null,tt.current=null,qe.current=null,Nt.clearAnimations(),xt.current={},un.current=0,zn(!1),Le.current&&(clearTimeout(Le.current),Le.current=null),bo.current=0,Ro(null),ji.current=void 0,$(null),I(""),H.forEach(r=>r.resolved?.cleanup()),de([]),Q([]),Ve.reset(Do),an([]),so([]),Ne(null),Ce(null),pn(null),ie.reset({}),vi("{}"),yi("{}"),wi(null),Si(null),Vr(null),Bi("select"),Ti(r=>Xe(r)),W(""),X("default")},fl=r=>c?{...r,bindingHistory:void 0}:r,Gb=()=>{Vn.length>1?rn(!0):Hi()},qb=()=>{rn(!1)},Wb=r=>{if(rn(!1),_.length<=1){Hi();return}if(!_.includes(r))return;if(at(),r!==P){let E=H.find(D=>D.url===r);E?.resolved?.cleanup(),de(D=>D.filter(F=>F.url!==r)),Q(D=>D.filter(F=>F!==r)),W(`Removed ${E?.name??"the model"}.`),X("success");return}let l=_.filter(E=>E!==r),b=l[0],S=H.findIndex(E=>E.url===b),k=H[S];if(!k){Hi();return}Je.current?.cleanup(),de(E=>E.filter((D,F)=>F!==S)),Q(l),Je.current=k.resolved??null,qe.current={model:k.sessionModel??{kind:"url",url:k.url,name:k.name}},Qt.current=null,tt.current=null,xt.current=k.originalTransforms,Nt.clearAnimations(),Ir(k),$(k.url),I(k.name),Ne(J.current.get(k.url)??{url:k.url,name:k.name}),ie.restoreModel(k),Ce(Object.keys(k.bindings)[0]??null),pn(null),W(`Removed the model \u2014 now viewing ${k.name}.`),X("success")},Yb=r=>{rn(!1);let l=Ee.find(k=>k.url===r);if(l){at(),ie.removeMerge(r),c&&ie.clearHistory(),W(`Removed ${Gt(l.namePrefix)}.`),X("success");return}let b=H.find(k=>k.mergedModelSources.some(E=>E.url===r));if(!b)return;let S=b.mergedModelSources.find(k=>k.url===r);S&&(at(),de(k=>k.map(E=>E.url!==b.url?E:fl(ts(E,D=>es(D,r))))),W(`Removed ${Gt(S.namePrefix)}.`),X("success"))},hl=()=>{v.current?.click()},ea=()=>{Er(!0)},Jb=r=>{let l=r.target.files?.[0];r.target.value="";let b=Mi.current;Mi.current=null,!(!l||!f||!b)&&(b.mode==="separate"?Qb(l):eg(l,b.targetUrl))},Xb=Z(()=>{Mi.current=null,Er(!1)},[]),Zb=Z(r=>{Mi.current=r,Er(!1),m.current?.click()},[]),ta=Z(async r=>{if(c&&g){W(`Uploading ${r.name}...`),X("default");let S=await g(r);J.current.set(S.url,S);let k=S.name??r.name;return{resolved:{url:S.url,name:k,format:"glb",cleanup:()=>{}},sessionModel:{kind:"url",url:S.url,name:k}}}let l=await ho(r),b=gs();return Zt.current.set(b,r),{resolved:l,sessionModel:{kind:"file",key:b,name:l.name}}},[c,g]),Qb=Z(async r=>{if(!St(fi.current,"models",Pi.current.modelOrder.length)){W("Your plan has no room for another model in this project. Upgrade to add more."),X("error");return}let l,b;try{({resolved:l,sessionModel:b}=await ta(r))}catch(S){W(S instanceof Error?S.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, or .zip asset."),X("error");return}de(S=>[...S,{url:l.url,name:l.name,bindings:{},originalTransforms:{},resolved:l,sessionModel:b,mergedModelSources:[]}]),Q(S=>[...S,l.url]),at(),W(`Added ${l.name} as a separate model.`),X("success")},[at,ta]),eg=Z(async(r,l)=>{let b,S;try{({resolved:b,sessionModel:S}=await ta(r))}catch(K){W(K instanceof Error?K.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, or .zip asset."),X("error");return}let k=Pi.current,E=k.parkedModels.find(K=>K.url===l);if(!k.modelOrder.includes(l)||l!==k.modelUrl&&!E){b.cleanup(),W("The destination model was removed. Choose a model and add the file again."),X("error");return}let D={url:b.url,resolved:b,sessionModel:S,nodeNames:[],loadState:"loading"};l===k.modelUrl?(ie.addMerge(K=>({...D,namePrefix:Za(b.name,K.mergeSources,K.bindings)})),c&&ie.clearHistory()):de(K=>{let le=K.findIndex(ke=>ke.url===l);if(le===-1)return K;let te=[...K];return te[le]=fl(ts(te[le],ke=>({...ke,mergeSources:[...ke.mergeSources,{...D,namePrefix:Za(b.name,ke.mergeSources,ke.bindings)}]}))),te});let F=l===k.modelUrl?k.modelName:E?.name;at(),W(`Merging ${b.name} into ${F||"the model"}...`),X("default")},[ie.addMerge,at]),tg=Z((r,l)=>{let b=Ee.find(K=>K.url===r);if(b){let{bindings:K,originalTransforms:le,nodeNames:te}=Qa(l,q);ie.hydrateMerge(r,{nodeNames:te,loadState:"loaded"},K),xt.current={...xt.current,...le},W(`Merged ${te.length} node${te.length===1?"":"s"} from ${b.namePrefix||"the added model"} into ${w||"the model"}.`),X("success");return}let S=H.find(K=>K.mergedModelSources.some(le=>le.url===r));if(!S)return;let k=S.mergedModelSources.find(K=>K.url===r);if(!k)return;let{bindings:E,originalTransforms:D,nodeNames:F}=Qa(l,S.bindings);de(K=>K.map(le=>le.url!==S.url?le:{...os(le,r,{nodeNames:F,loadState:"loaded"},E),originalTransforms:{...le.originalTransforms,...D}})),W(`Merged ${F.length} node${F.length===1?"":"s"} from ${k.namePrefix||"the added model"} into ${S.name||"the model"}.`),X("success")},[ie.hydrateMerge,w,Ee,q,H]),og=Z((r,l)=>{let b=Ee.find(k=>k.url===r)??H.flatMap(k=>k.mergedModelSources).find(k=>k.url===r);if(!b)return;ie.hydrateMerge(r,{loadState:"failed"}),de(k=>k.map(E=>E.mergedModelSources.some(D=>D.url===r)?os(E,r,{loadState:"failed"}):E));let{detail:S}=qi(l,r,b.resolved.format);W(`Could not merge ${b.resolved.name}. ${S} Remove the failed file using the Remove model menu.`),X("error")},[Ee,H,ie.hydrateMerge]),ng=Z((r,l)=>{let b=H.find(k=>k.url===r);if(!b)return;let{detail:S}=qi(l,r,b.resolved?.format);W(`Could not read ${b.name}. ${S} Remove the failed file using the Remove model menu.`),X("error")},[H]),ig=Z((r,l)=>{yt.current.get(r)!==l&&(yt.current.set(r,l),Qs(b=>b+1)),de(b=>{let S=b.findIndex(F=>F.url===r);if(S===-1)return b;let{bindings:k,originalTransforms:E}=pi(l,b[S].bindings),D=[...b];return D[S]={...Kp(D[S],k),bindings:Xo(l,b[S].bindings,b[S].mergedModelSources,k),originalTransforms:{...E,...b[S].originalTransforms}},D})},[]),zo=Z(r=>{if(r===P)return;let l=H.findIndex(k=>k.url===r);if(l===-1)return;let b=H[l];$n.current?.(),at();let S=P?{url:P,name:w,bindings:q,originalTransforms:xt.current,resolved:Je.current??void 0,sessionModel:qe.current?.model,mergedModelSources:Ee,modelSettings:xo(ee),bindingHistory:ie.snapshot,sceneHistory:Be.snapshot}:null;de(k=>{let E=k.filter((D,F)=>F!==l);return S?[...E,S]:E}),Je.current=b.resolved??null,qe.current={model:b.sessionModel??{kind:"url",url:b.url,name:b.name}},Qt.current=null,tt.current=null,Nt.clearAnimations(),Ir(b),xt.current=b.originalTransforms,$(b.url),I(b.name),Ne(J.current.get(b.url)??{url:b.url,name:b.name}),ie.restoreModel(b),Ce(Object.keys(b.bindings)[0]??null),pn(null)},[P,w,q,H,ie,Ee,ee,Be,Ir,Nt.clearAnimations,at]),rg=()=>{A.current?.click()};ze(()=>{P&&me.length&&!me.some(r=>r.url===P)&&zo(me[0].url)},[P,me,zo]);let{handleExportBindings:xl,handleExportSceneConfig:vl,handleImportBindingsChange:ag,openSceneConfigImportPicker:sg,handleImportSceneConfigChange:lg}=fu({bindings:q,setBindings:To,sceneConfig:ee,setSceneConfig:Rt,nodeKeys:Ht,sceneConfigInputRef:G,setIsExporting:Ou,setStatusMessage:W,setStatusTone:X}),dg=r=>{r.preventDefault(),r.stopPropagation(),!(Me||P)&&(un.current+=1,zn(!0))},cg=r=>{r.preventDefault(),r.stopPropagation(),!(Me||P)&&(r.dataTransfer.dropEffect="copy",zn(!0))},pg=r=>{r.preventDefault(),r.stopPropagation(),!(Me||P)&&(un.current=Math.max(0,un.current-1),un.current===0&&zn(!1))},ug=async r=>{if(r.preventDefault(),r.stopPropagation(),un.current=0,zn(!1),Me||P)return;let l=r.dataTransfer.files?.[0];l&&await ml(l)},yl=(r,l,b)=>{if(!L)return;let S;try{S=JSON.parse(l)}catch{b("Invalid JSON");return}if(S===null||typeof S!="object"||Array.isArray(S)){b("Expected a JSON object");return}if(r==="metrics"&&Object.values(S).some(E=>typeof E!="number"||!Number.isFinite(E))){b("Metrics values must be numbers");return}wt(L,k=>({...k,[r]:S})),b(null)},wl=Z((r,l)=>{Fi&&wn(r,l).catch(b=>console.warn("[BindingBuilder] Could not store decal image for autosave:",b))},[Fi]),bg=Ue(()=>{let r=Qt.current?.scene,b=(r&&L?Gn(r,L):null)?.geometry;if(!b)return .2;b.boundingBox||b.computeBoundingBox();let S=b.boundingBox?.getSize(new Ox),k=S?Math.max(S.x,S.y,S.z):0;return k>0&&Number.isFinite(k)?k/3:.2},[L,P,Me]),gg=Ue(()=>{if(!xi?.moving)return null;let{nodeKey:r,decal:l}=xi,b=q[r],S=b?.decals?.find(k=>k.id===l.id);return S?{objectId:b.modelObjectId??r,decal:S,onCancel:()=>lo(null),onCommit:k=>{To(E=>{let D=E[r];return D?{...E,[r]:{...D,decals:D.decals?.map(F=>F.id===S.id?{...F,...k}:F)}}:E}),lo(null)}}:null},[q,xi,To]),mg=Z((r,l)=>{if(!L)return;let b=q[L],S=b?.decals?.find(F=>F.id===r);if(!S)return;let k=jo.current,E=k?.raw.nodes[b.modelObjectId??L],D=pd(E,k?.raw.controls.camera,S,l);if(!D){W("No visible surface in that direction. Try another arrow or rotate the view."),X("error");return}lo(null),wt(L,F=>({...F,decals:F.decals?.map(K=>K.id===r?{...K,...D}:K)}))},[q,L,wt]),fg=Z(r=>{if(!r||r.moving){lo(r);return}let l=jo.current,b=q[r.nodeKey],S=l?.raw.nodes[b?.modelObjectId??r.nodeKey],k=cd(S,l?.raw.controls.camera);if(!k){W("Could not find a surface on this object for the decal."),X("error");return}let E={...r.decal,...k};To(D=>{let F=D[r.nodeKey];if(!F)return D;let K=(F.decals??[]).filter(le=>le.id!==E.id);return{...D,[r.nodeKey]:{...F,decals:[...K,E]}}}),lo({...r,moving:!0})},[q,To]),hg=Z((r,l)=>{let b=Object.entries(q).find(([F,K])=>K===r||F===r.modelObjectId||K.modelObjectId===r.modelObjectId)?.[0],S=b?q[b]?.decals?.find(F=>F.id===l):void 0;if(!b||!S)return;on("object"),Ts(F=>({...F,decals:!0})),Ce(b);let{position:k,normal:E,...D}=S;setTimeout(()=>lo({nodeKey:b,decal:D,moving:!0}),0)},[q]),xg=Z(r=>{let l=[...new Set(r)].filter(b=>q[b]&&!q[b].removed);fs(l)},[q,fs]),vg=Z(r=>{let l=mi.current;if(mi.current={shiftKey:!1,ctrlKey:!1,metaKey:!1},Ge){$r("orbit");return}if(!r){En(null);return}let b=Object.entries(q).find(([S,k])=>k===r||S===r.modelObjectId||k.modelObjectId===r.modelObjectId)?.[0]??null;En(b,l)},[Ge,q,En]),oa=Z(async r=>{if(Ge){$r("orbit");return}En(r),!tn&&(Vr(null),await _n(r))},[Ge,_n,tn,En]),yg=Z(r=>{Vr(r?q[r]??null:null)},[q]),wg=Z(()=>{if(Ge){W("Camera positions aren't available while Pointer Lock is the active camera controller."),X("error");return}if(!L||!Pe)return;let r={position:Pe.position,target:Pe.target,...Pe.fov!=null?{fov:Pe.fov}:{},zoom:Pe.zoom};wt(L,l=>({...l,cameraState:r}))},[Ge,L,Pe]),Sg=Z(()=>{if(Ge){W("Camera positions aren't available while Pointer Lock is the active camera controller."),X("error");return}!mo?.position||!mo?.target||zi({position:mo.position,target:mo.target,fov:mo.fov??Pe?.fov??null,zoom:mo.zoom??Pe?.zoom??1},!0)},[Ge,mo,zi,Pe]),kg=Z(()=>{Ge||L&&wt(L,r=>({...r,cameraState:void 0}))},[Ge,L]),Sl=Z(async()=>{if(Ge){W("Reset view isn't available while Pointer Lock is the active camera controller."),X("error");return}await sl()},[Ge,sl]),Kn=Z(async()=>{if(Ge){W("Fit scene isn't available while Pointer Lock is the active camera controller."),X("error");return}await ll()},[Ge,ll]),Cg=Z(()=>{W("Texture position saved."),X("success"),Ys.current?.()},[]),Mg=Z(r=>{Hs(r),Fs(!0)},[]),$i=Z(()=>{Fs(!1),Hs(null)},[]),Pg=Z(()=>{if(Dn==="bindings"){if(!Ht.length){$i();return}let r=Yn(Ht,rl);ie.reset(r,{asEdit:!0}),Ce(Ht[0]??null),W("Object bindings reset to default values."),X("success")}else Dn==="assets"?(Ve.setValueAsStep(r=>({...r,gridSize:Do.gridSize,placements:Object.fromEntries(Object.entries(r.placements).map(([l,b])=>{let{position:S,rotation:k,scale:E,...D}=b;return[l,D]}))})),W("Asset placements reset to default values."),X("success")):Dn==="scene"&&(Be.reset(fo,{asEdit:!0}),W("Scene config reset to default values."),X("success"));$i()},[Dn,Ht,ie,Be,Ve,$i]),Bg=Z(r=>{r.length>0&&jr(r)},[]),Tg=Z(()=>{jr(null)},[]),Rg=Z(()=>{let r=uo;if(!r||r.length===0)return;let l=new Set(r);ie.setValueAsStep(b=>{let S={...b};for(let k of r)b[k]&&(S[k]={...b[k],removed:!0});return S}),Ce(b=>b&&l.has(b)?null:b),xr(b=>b.filter(S=>!l.has(S))),In(b=>b&&l.has(b)?null:b),W(r.length===1?`Deleted ${q[r[0]]?.label||r[0]}.`:`Deleted ${r.length} objects.`),X("success"),jr(null)},[uo,q,ie.setValueAsStep]),Ng=Z(()=>{Or(null)},[]),Ag=async()=>{let r;try{r=await Hd()}catch(l){console.warn("[BindingBuilder] Could not read the saved session:",l),W("Couldn't read the saved session from this browser."),X("error");return}if(!r){W("No saved session in this browser. Sessions are saved when you edit a model or add another one."),X("error");return}Or(r)},na=async(r,l)=>(await Promise.all(r.map(async({entry:S,file:k})=>{if(S.model.kind==="url"&&c)return Sn({url:"",objectBindings:{},mergeModels:[{url:S.model.url,namePrefix:S.namePrefix}]})[0];if(S.model.kind==="url")return console.warn(`[BindingBuilder] Could not restore merged model "${S.model.name}" \u2014 merged models must come from an uploaded file.`),null;if(!k)return console.warn(`[BindingBuilder] Could not restore merged model "${S.model.name}" \u2014 its file is no longer in this browser's storage.`),null;try{let E=await ho(k);return l.set(S.model.key,k),{url:E.url,namePrefix:S.namePrefix,resolved:E,sessionModel:S.model,nodeNames:[],loadState:"loading"}}catch(E){return console.warn(`[BindingBuilder] Could not restore merged model "${S.model.name}":`,E),null}}))).filter(S=>S!==null),Og=async(r,l,b)=>{let S=await Promise.all(r.map(async({entry:E,file:D,mergeFiles:F})=>{if(await gi(E.modelSettings?.product),E.model.kind==="url")return{url:E.model.url,name:E.model.name,bindings:await Qo(E.bindings),originalTransforms:E.originalTransforms,modelSettings:E.modelSettings,sessionModel:E.model,mergedModelSources:await na(F,b)};if(!D)return console.warn(`[BindingBuilder] Could not restore parked model "${E.model.name}" \u2014 its file is no longer in this browser's storage.`),null;try{let K=await ho(D);return b.set(E.model.key,D),{url:K.url,name:E.model.name,bindings:await Qo(E.bindings),originalTransforms:E.originalTransforms,modelSettings:E.modelSettings,resolved:K,sessionModel:E.model,mergedModelSources:await na(F,b)}}catch(K){return console.warn(`[BindingBuilder] Could not restore parked model "${E.model.name}":`,K),null}})),k=await na(l,b);return{parkedModels:S.filter(E=>E!==null),mergedModelSources:k}},ia=(r,l)=>{Ve.setValue(b=>({...b,placements:{...b.placements,[r]:{...b.placements[r],...l}}}))},Eg=async r=>{if(sn||!f||!el)return;let l=r===P?{url:r,name:w,bindings:q,originalTransforms:xt.current,resolved:Je.current??void 0,sessionModel:qe.current?.model,mergedModelSources:Ee,modelSettings:xo(ee)}:H.find(k=>k.url===r);if(!l?.sessionModel)return;if(c){let k=`${r.split("#")[0]}#copy-${crypto.randomUUID()}`,E=Vo(k),D=J.current.get(r);J.current.set(k,{...D,url:k});let F=`${l.name} copy`,K=structuredClone(l.modelSettings);K?.measurements&&(K.measurements.items=K.measurements.items.map(we=>({...we,modelId:E}))),de(we=>[...we,{...l,url:k,name:F,resolved:void 0,sessionModel:{kind:"url",url:k,name:F},bindings:structuredClone(l.bindings),originalTransforms:structuredClone(l.originalTransforms),modelSettings:K,mergedModelSources:l.mergedModelSources.map(Ot=>({...Ot,loadState:"loading"})),bindingHistory:void 0,sceneHistory:void 0}]),Q(we=>[...we,k]),an(we=>[...we,E]);let le=Un(r),[te,ke,ct]=le.position??[0,0,0];Ve.setValueAsStep(we=>({...we,placements:{...we.placements,[E]:{...le,deleted:!1,label:`${le.label??l.name} copy`,position:[te+rt.gridSize,ke,ct]}}})),at(),W(`Duplicated ${l.name}.`),X("success");return}ln(!0);let b=vt.current,S=[];try{let E=(l.sessionModel.kind==="file"?Zt.current.get(l.sessionModel.key):void 0)??new File([await(await fetch(l.url)).blob()],l.name),D=await ho(E);S.push(D);let F=gs(),K=`file:${F}`,le=[];for(let fe of l.mergedModelSources){if(fe.sessionModel.kind!=="file")throw new Error("Cannot duplicate a merged source without its original file.");let ot=Zt.current.get(fe.sessionModel.key);if(!ot)throw new Error("An added source file is unavailable.");let Et=await ho(ot);S.push(Et),le.push({...fe,resolved:Et,url:Et.url,loadState:"loading"})}if(b!==vt.current||!Pi.current.modelOrder.includes(r)){S.forEach(fe=>fe.cleanup());return}Zt.current.set(F,E);let te=structuredClone(l.modelSettings);te?.measurements&&(te.measurements.items=te.measurements.items.map(fe=>({...fe,modelId:K}))),de(fe=>[...fe,{...l,url:D.url,name:`${l.name} copy`,resolved:D,sessionModel:{kind:"file",key:F,name:E.name},bindings:structuredClone(l.bindings),originalTransforms:structuredClone(l.originalTransforms),modelSettings:te,mergedModelSources:le,bindingHistory:void 0,sceneHistory:void 0}]),Q(fe=>[...fe,D.url]),an(fe=>[...fe,K]);let ke=Un(r),[ct,we,Ot]=ke.position??[0,0,0];Ve.setValueAsStep(fe=>({...fe,placements:{...fe.placements,[K]:{...ke,deleted:!1,label:`${ke.label??l.name} copy`,position:[ct+rt.gridSize,we,Ot]}}})),at(),W(`Duplicated ${l.name}.`),X("success")}catch(k){S.forEach(E=>E.cleanup()),W(k instanceof Error?k.message:"Could not duplicate asset."),X("error")}finally{ln(!1)}},jg=r=>{if(me.length<2||!f)return;let l=me.find(b=>b.url===r);l&&(r===P&&zo(me.find(b=>b.url!==r).url),Ve.setValueAsStep(b=>({...b,placements:{...b.placements,[l.id]:{...b.placements[l.id],deleted:!0}}})))},kl=async r=>{if(!(sn||!f)){if(!nt(fi.current,"sceneBundle")){W(`Importing a complete scene requires the ${ua.starter} plan or higher.`),X("error");return}ln(!0);try{let l=await Yd(r);if(c){if(!g)throw new Error("This project can't accept new models.");let b=S=>l.session.composition?.placements[Ut(S)]?.deleted;if(1+l.parkedFiles.filter(S=>!b(S.entry.model)).length>Js)throw new Error(`Your plan allows ${Js} models per project. Upgrade to import this scene.`);W(`Uploading the models in ${r.name}...`),X("default"),l=await Kd(l,async S=>{let k=await g(S);return J.current.set(k.url,k),k})}await Cl(l),at()}catch(l){W(l instanceof Error?l.message:"Could not load scene bundle."),X("error")}finally{ln(!1)}}},Ig=async()=>{let r=qe.current;if(!(!r||!P||sn)){ln(!0);try{let l=k=>({model:k.sessionModel,namePrefix:k.namePrefix}),b={model:r.model,bindings:q,sceneConfig:ee,composition:rt,mergeModels:Ee.map(l),parkedModels:H.map(k=>({model:k.sessionModel??{kind:"url",url:k.url,name:k.name},bindings:k.bindings,originalTransforms:k.originalTransforms,modelSettings:k.modelSettings,mergeModels:k.mergedModelSources.map(l)})),modelOrder:_.map(k=>go.get(k)).filter(Boolean)},S=await Wd(b,new Map(Zt.current));fn(S,"scene.ri.zip"),W("Saved complete scene bundle."),X("success")}catch(l){W(l instanceof Error?l.message:"Could not save scene."),X("error")}finally{ln(!1)}}},Cl=async r=>{let l=r??Ao;if(Or(null),!l)return;let{session:b,file:S}=l,{model:k}=b;$n.current=null;let E=vt.current,D=await mu(ei(fo,b.sceneConfig));await gi(D.product);let F=await Qo(b.bindings);if(await hr(D),vt.current!==E)return;let K=new Map,{parkedModels:le,mergedModelSources:te}=await Og(l.parkedFiles,l.mergeFiles,K);if(vt.current!==E){le.forEach(ci),te.forEach(On);return}let ke=fe=>{let ot=new Map;ot.set(Ut(k),fe),le.forEach(jt=>{jt.sessionModel&&ot.set(Ut(jt.sessionModel),jt.url)});let Et=(b.modelOrder??[]).map(jt=>ot.get(jt)).filter(jt=>!!jt),Tl=new Set(Et);for(let jt of[fe,...le.map(Fg=>Fg.url)])Tl.has(jt)||(Et.push(jt),Tl.add(jt));return Et},ct=()=>{for(let[fe,ot]of K)Zt.current.set(fe,ot),r?Ii.current.delete(fe):Ii.current.add(fe)},we;if(k.kind==="file"){if(!S){le.forEach(ci),te.forEach(On);return}let fe=vt.current,ot;try{ot=await ho(S)}catch(Et){console.warn("[BindingBuilder] Could not read the saved model:",Et),W(ms(k.name)),X("error"),le.forEach(ci),te.forEach(On);return}if(vt.current!==fe){ot.cleanup(),le.forEach(ci),te.forEach(On);return}Je.current?.cleanup(),Je.current=ot,we=ot.url,K.set(k.key,S),ct(),zr(),H.forEach(Et=>Et.resolved?.cleanup()),de(le),so(te),Q(ke(we)),Ve.reset(b.composition?Fo(b.composition):Do),an([])}else{we=k.url,ct(),zr(),H.forEach(ot=>ot.resolved?.cleanup()),de(le),so(te),Q(ke(we)),Ve.reset(b.composition?Fo(b.composition):Do),an([]);let fe=Qt.current;if(we===P&&fe?.url===we&&!tt.current){qe.current={model:k},ie.reset(Xo(fe.scene,F,te,pi(fe.scene,F).bindings)),Be.reset(D),W(`Restored your last session with ${k.name}.`),X("success");return}Je.current?.cleanup(),Je.current=null}qe.current={model:k,file:S??void 0},k.kind==="file"&&!r&&Ii.current.add(k.key);let Ot=++vt.current;we!==P&&Nt.clearAnimations(),qt(!0),Ro(null),bo.current=0,Le.current&&(clearTimeout(Le.current),Le.current=null),ji.current=S?.size,W("Restoring your last session."),X("default"),I(k.name),Ne({url:we,name:k.name}),pn(null),Ce(null),Qt.current=null,ie.reset({}),Be.reset(D),tt.current={requestId:Ot,modelName:k.name,modelUrl:we,storedBindings:F,restoring:!0},$(we)};ze(()=>{let r=l=>{if((l.metaKey||l.ctrlKey)&&l.key.toLowerCase()==="k"){l.preventDefault(),Mr(S=>!S);return}if(l.metaKey||l.ctrlKey||l.altKey||Pu(l.target,!0))return;if(l.key==="?"){l.preventDefault(),Pr(S=>!S);return}if(!P)return;let b=sr.find(S=>S.shortcut.toLowerCase()===l.key.toLowerCase());b?(l.preventDefault(),Bi(b.id)):l.key.toLowerCase()==="f"&&(l.preventDefault(),L?_n(L):Kn())};return window.addEventListener("keydown",r),()=>window.removeEventListener("keydown",r)},[P,L,_n,Kn]);let bn=Zc();if(Hn.status==="checking")return R("div",{className:"bb-root bb-root--licenseChecking",children:!u&&R(la,{title:"Validating license key\u2026"})});if(Hn.status==="invalid")return R("div",{className:"bb-root bb-root--licenseInvalid",children:R(la,{tone:"error",title:"Invalid license",message:Hn.isLocalDomain?Hn.reason??"License has been revoked or has expired":"Failed to load. Please contact the site administrator."})});let Ml=(Tt==="annotations"||wr.open&&ki==="cinematic")&&Pe?{position:Pe.position,target:Pe.target,azimuthAngle:Pe.azimuthAngle,polarAngle:Pe.polarAngle,fov:Pe.fov,zoom:Pe.zoom}:null,zg=P?eo.get(P)??"Model":"Untitled scene",Lo=Oe&&!Cu.find(r=>r.id===Ms)?.group?"general":Ms,Lg=r=>{r.panel==="object"?(Wt.setOpen(!0),on("object"),Ps(r.tab)):r.panel==="scene"?(Wt.setOpen(!0),on("scene"),Tr(r.tab)):r.panel==="configure"?(on("configure"),No("scene")):r.panel==="left"?(co.setOpen(!0),Sr(r.tab)):(Cs(r.tab),wr.setOpen(!0)),r.section&&bp(r.section)},Dg=()=>[...sr.map(r=>({id:`tool-${r.id}`,label:`${r.label} tool`,hint:"Tool",shortcut:r.shortcut,run:()=>Bi(r.id)})),{id:"frame",label:"Frame selection",hint:"Camera",shortcut:"F",run:()=>{L?_n(L):Kn()}},{id:"fit",label:"Fit scene",hint:"Camera",run:()=>{Kn()}},{id:"reset-view",label:"Reset view",hint:"Camera",run:()=>{Sl()}},{id:"code",label:"Show code",hint:"Code panel",keywords:"json typescript export",run:()=>{Wt.setOpen(!0),kr(!0)}},{id:"compare",label:"Compare before and after",hint:"Preview",run:()=>Vs(!0)},{id:"shortcuts",label:"Keyboard shortcuts",hint:"Help",shortcut:"?",run:()=>Pr(!0)},...f?[{id:"add-model",label:"Add model",hint:"Model",keywords:"upload import asset",run:ea}]:[],...up.map(r=>({id:`setting-${r.label}-${r.where.tab}`,label:r.label,hint:r.hint,keywords:r.keywords,run:()=>Lg(r.where)}))],Pl=[{title:"Scene settings",description:"Lighting, camera, and environment for the active model. No model files or bindings.",onImport:sg,onExportJson:()=>vl("json"),onExportTs:()=>vl("ts"),importDisabled:!Ht.length||Me,exportDisabled:!Ht.length||Me},{title:"Object bindings",description:"Bindings for the active model, with uploaded textures when available. No model files or scene settings.",onImport:rg,onExportJson:()=>xl("json"),onExportTs:()=>xl("ts"),importDisabled:!Ht.length||Me,exportDisabled:!Ht.length||Me}],Bl=f&&nt(Eo,"sceneBundle")?{onImport:()=>_s.current?.click(),onExport:Ig,importDisabled:Me,exportDisabled:Me||!me.length||me.some(r=>!r.ready)}:void 0,ra=Ge?R(et,{children:"Click the preview to look around \xB7 Esc to release"}):Xt!=="select"&&!L?R(et,{children:"Select an object to transform it"}):Xt==="move"?R(et,{children:"Drag an arrow or plane to move"}):Xt==="rotate"?R(et,{children:"Drag a ring to rotate"}):Xt==="scale"?R(et,{children:"Drag the handle to scale"}):db&&Ar?ae(et,{children:[ae("span",{children:[R("kbd",{children:"W"}),R("kbd",{children:"A"}),R("kbd",{children:"S"}),R("kbd",{children:"D"})," move"]}),ae("span",{children:["\xB7 ",R("kbd",{children:"Space"}),"/",R("kbd",{children:"C"})," up \xB7 down"]}),R("span",{children:"\xB7 drag to look"})]}):null;return ae(od.Provider,{value:gb,children:[ae("div",{className:"bb-root","data-input":"pointer",onPointerDownCapture:r=>{r.currentTarget.dataset.input="pointer"},onKeyDownCapture:r=>{r.key==="Tab"&&(r.currentTarget.dataset.input="keyboard")},onMouseOver:bn.onMouseOver,onContextMenu:bn.onContextMenu,onKeyDown:r=>{r.key!=="Escape"||r.defaultPrevented||!Oe||r.target.closest('input:not([type="checkbox"]), textarea, select, [contenteditable="true"]')||(r.preventDefault(),r.stopPropagation(),tn?hs():xs())},children:[R("input",{ref:v,type:"file",accept:sa,className:"bb-hiddenInput",onChange:Kb,disabled:Me}),R("input",{ref:m,type:"file",accept:sa,className:"bb-hiddenInput",onChange:Jb,disabled:Me}),R("input",{ref:A,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:ag,disabled:Me}),R("input",{ref:G,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:lg,disabled:Me}),R("input",{ref:_s,type:"file",accept:".zip,application/zip",hidden:!0,onChange:async r=>{let l=r.target.files?.[0];r.target.value="",l&&await kl(l)}}),R(Yc,{modelName:zg,modelMenu:f||me.length>1?r=>R(Zd,{close:r,models:me.length>1?me.map(l=>({url:l.url,label:eo.get(l.url)??l.name})):void 0,activeModelUrl:P,onSelectModel:zo,onRestore:!f||P||c?void 0:Ag,restoreDisabled:Me,onAddModel:f&&P?ea:void 0,onUpload:f&&!P?hl:void 0,addModelDisabled:Me,onReset:f&&P?()=>Mg(Ln):void 0,resetLabel:`Reset ${Mu[Ln]} changes\u2026`,onRemove:f&&P&&(!c||Vn.length>1)?Gb:void 0,confirmRemove:Vn.length<=1}):void 0,canUndo:Io.canUndo,canRedo:Io.canRedo,undoTarget:Mu[Ln],onUndo:Io.undo,onRedo:Io.redo,tool:Xt,onToolChange:r=>{Bi(r),r!=="select"&&No("bindings")},space:$s,onSpaceChange:ob,hasModel:!!P,compareOpen:Oo,onToggleCompare:()=>{Vs(r=>!r),Dr(null)},codeOpen:Bs,onToggleCode:()=>kr(r=>!r),onOpenCommands:()=>Mr(!0),start:e,xrToolsSlot:Vu,fileActions:ae(et,{children:[R(Wc,{scopes:Pl,sceneBundle:Bl,busy:sn||ys}),R(qc,{scopes:Pl,sceneBundle:Bl,busy:sn||ys})]})}),ae("div",{className:`bb-workspace ${po?"bb-workspace--customerPreview":""}`,children:[co.open?ae(et,{children:[ae("aside",{className:"bb-panel bb-panel--left",style:{width:co.size},onPointerDownCapture:()=>{Tt==="assets"&&No("assets"),Tt==="annotations"&&No("scene")},children:[ae("div",{className:"bb-tabs",role:"tablist","aria-label":"Scene contents",children:[Zx.filter(r=>r.id!=="assets"||f).map(r=>R("button",{type:"button",role:"tab","aria-selected":Tt===r.id,className:`bb-tab ${Tt===r.id?"bb-tab--active":""}`,onClick:()=>Sr(r.id),children:r.label},r.id)),R("span",{className:"bb-topBarSpacer"}),R("button",{type:"button",className:"bb-toolButton bb-toolButton--small","aria-label":"Hide left panel",title:"Hide panel",onClick:()=>co.setOpen(!1),children:R(Fx,{size:14})})]}),R("div",{className:`bb-panelBody ${Tt==="outliner"?"bb-panelBody--fill":""}`,children:Tt==="outliner"?R(Fp,{bindings:q,selectedItem:L,onSelect:oa,onHover:yg,modelGroups:Ab,onSelectModel:zo,isolatedItem:hi,onIsolate:In,multiSelectEnabled:tn,onToggleMultiSelect:Tu,onExitMultiSelect:hs,multiSelectedKeys:_e,onSetMultiSelected:xg,hierarchy:yb,selectionSets:ee.selectionSets,onSelectionSetsChange:nb}):P?Tt==="assets"?R(Aa,{assets:me.map(r=>({...r,displayName:eo.get(r.url)})),activeUrl:P,composition:rt,busy:sn||Me,onFrameAll:()=>{let r=new Su;for(let b of me){if(b.placement.visible===!1)continue;let S=yt.current.get(b.url);S&&(S.updateWorldMatrix(!0,!0),r.union(new Su().setFromObject(S)))}let l=jo.current;!r.isEmpty()&&l&&(bd(r,l.raw.controls),l.raw.controls.fitToBox(r,!0,gd).then(()=>l.invalidate()))},onSelect:zo,onAdd:ea,addRequiresTier:el?void 0:Ho("models",me.length),onChange:ia,onGridSize:r=>Ve.setValue(l=>({...l,gridSize:r})),onDuplicate:r=>{Eg(r)},onDelete:c?()=>rn(!0):jg,deleteIsPermanent:!!c,onSnap:r=>ia(r,Dl(rt.placements[r]??{},rt.gridSize)),onGround:r=>{let l=yt.current.get(r),b=l?Hl(l):null;b&&ia(go.get(r),Fl(Un(r),b))}}):Tt==="annotations"?R(Gx,{config:ee,onChange:Rt,cameraState:Ml,onPreviewView:pl}):R("div",{ref:As,className:"bb-measurePanel"}):R("p",{className:"bb-panelEmpty",children:"Open a model to use this."})})]}),R(ii,{orientation:"vertical",label:"Resize left panel",onPointerDown:co.startResize,onKeyDown:co.onResizeKey})]}):R("button",{type:"button",className:"bb-panelReveal bb-panelReveal--left","aria-label":"Show left panel",title:"Show panel",onClick:()=>co.setOpen(!0),children:R(Hx,{size:14})}),ae("main",{className:"bb-previewShell",children:[ae("div",{className:"bb-preview",ref:N,onPointerDownCapture:r=>{mi.current={shiftKey:r.shiftKey,ctrlKey:r.ctrlKey,metaKey:r.metaKey}},onKeyDownCapture:()=>{mi.current={shiftKey:!1,ctrlKey:!1,metaKey:!1}},onFocus:r=>{r.currentTarget.contains(r.relatedTarget)||_r()},children:[P?ae("div",{className:"bb-viewportBar",children:[R(Zn,{label:"View",icon:R(Dx,{size:13,"aria-hidden":"true"}),title:"Preview options",children:()=>ae(et,{children:[ae("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Ds,onChange:r=>Wu(r.target.checked)}),"Zoom on selected"]}),ae("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Nr,onChange:r=>Yu(r.target.checked)}),"Highlight on hover"]}),ae("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Ar,onChange:r=>Ju(r.target.checked)}),"Camera controls"]}),ae("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Cr,onChange:r=>Du(r.target.checked)}),"Floor grid"]})]})}),ae("label",{className:"bb-topBarSelect",title:"Renderer","data-ri-path":"sceneConfig.model.renderer",children:[R("span",{className:"bb-visuallyHidden",children:"Renderer"}),ae("select",{value:ee.model.renderer,onChange:r=>Rt({...ee,model:{...ee.model,renderer:r.target.value}}),children:[R("option",{value:"pbr",children:"PBR"}),R("option",{value:"matcap",children:"Matcap"}),R("option",{value:"uv-checker",children:"UV checker"})]}),R(jx,{size:12,"aria-hidden":"true"})]})]}):null,R(rd,{visible:Me,title:w||void 0,message:vr,progress:mb??void 0}),P&&R("div",{className:`bb-canvasHint ${ra?"bb-canvasHint--visible":""} ${Oo?"bb-canvasHint--belowCompare":""}`,"aria-hidden":!ra,children:ra}),po?R("button",{type:"button",className:"bb-customerPreviewExit",onClick:()=>Br(!1),children:"Previewing as a customer \xB7 Exit"}):null,P?R(ba,{loading:"eager",enableXR:!0,arHandoff:o,mobileHandoffUrl:n,modelUrl:P,tilesetUrl:j?.tilesetUrl,models:Ob,onModelChange:zo,onExtraModelLoaded:ig,onExtraModelError:ng,mergeModels:Yr,onMergeModelLoaded:tg,onMergeModelError:og,originalNodePoses:xt.current,objectBindings:q,comparisonHighlights:Ks?.after,selectedObject:Se,selectedObjectRefs:Cb,selectedObjectOutlineColor:"#35c0dc",onObjectSelect:vg,onSelectionClear:xs,onObjectBindingsChange:To,onTextureUpload:zb,onObjectEditLeaseChange:(r,l)=>T?.(`${P}|${r.modelObjectId||r.id}`,l),showObjectBindingDataPanel:!1,showSceneObjectsPanel:!1,onCameraChange:Bb,onViewerReady:r=>{jo.current=r,kb(r.raw.nodes),Mb(r)},onAnnotationsChange:jb,activeAnnotation:ub?.annotation??null,onActiveAnnotationChange:Ib,onSequencesReady:Sb,showSequenceControls:!1,sequenceAutoPlay:!1,onAnimationsReady:Vb,onModelAnimationsReady:At.handleModelAnimationsReady,onSceneLoaded:Hb,onAssetDiagnostics:qr?r=>ol({url:P,report:r}):void 0,onRuntimeStats:qr?nl:void 0,onLoadError:Ub,onObjectCatalog:j?.tilesetUrl?$b:void 0,onProgress:_b,onCameraControllerChange:$r,cameraControllerType:Gs,onTexturePositioningChange:cb,endTexturePositioningRef:Ys,licenseKey:i,licenseValidationUrl:a,dracoDecoderPath:d,ktx2TranscoderPath:s,meshopt:p,sceneConfig:Rb,onSceneConfigChange:Nb,productOptions:po?!0:void 0,preserveDrawingBuffer:!0,disableZoom:!1,zoomOnSelected:Ds,highlightOnHover:Nr,enableCameraControls:Ar,moveModeEnabled:eb,scaleModeEnabled:tb,gizmoTool:Xt==="rotate"?"rotate":"move",showFloorGrid:Cr&&!po,objectTransformSpace:$s,enableKeyboardNavigation:!0,showViewGizmo:!po,showMeasureTools:!0,measurementModelId:qe.current?.model.kind==="file"?Ut(qe.current.model):void 0,showSectionTools:!0,isolation:Nu,onIsolationChange:()=>In(null),showIsolateControls:!0,decalMove:gg,onDecalDoubleClick:hg,panelHoveredObject:Nr?bb:null,showLoadingOverlay:!1,autoRotate:Ge?!1:ee.model.autoRotate??!1,autoRotateSpeed:ee.model.autoRotateSpeed??1}):R("div",{className:`bb-previewPlaceholder ${Lu?"bb-previewPlaceholder--dragActive":""}`,onDragEnter:dg,onDragOver:cg,onDragLeave:pg,onDrop:ug,children:ae("div",{className:"bb-dropCard",children:[R(Ex,{size:18,"aria-hidden":"true"}),R("h3",{children:"Drop a model to start"}),R("p",{children:"Each object becomes a binding you can edit and export as code."}),R("div",{className:"bb-formatChips","aria-label":"Supported formats",children:["GLB","GLTF","OBJ","FBX","USDZ","STL","PLY","ZIP"].map(r=>R("span",{children:r},r))}),f?R("button",{type:"button",className:"bb-button bb-button--primary",onClick:hl,disabled:Me,children:"Choose file"}):null]})}),P&&Oo?R(tc,{showOutlines:Lr,onShowOutlinesChange:sb,matchBy:Fr,onMatchByChange:r=>{lb(r),Hr(null)},report:Fn??void 0,selected:Ri,onSelect:r=>{Hr(r?.id??null),r?.afterKey&&oa(r.afterKey)},liveViewerRef:jo,split:rb,onSplitChange:ab,labels:[dn?"Pinned":"Before","Now"],beforeAction:ae("button",{type:"button",className:"ri-compare__labelAction",onClick:()=>Dr(r=>r?null:{bindings:q,sceneConfig:ee}),"aria-pressed":!!dn,title:dn?"Unpin: compare with the project as it was opened again":"Pin as before: compare later changes with how the preview looks now",children:[dn?R(Vx,{size:12}):R(_x,{size:12}),dn?"Unpin":"Pin"]}),renderBefore:r=>R(ba,{loading:"eager",modelUrl:P,tilesetUrl:j?.tilesetUrl,comparisonHighlights:Ks?.before,objectBindings:cn.bindings,sceneConfig:{...cn.sceneConfig,section:ee.section},licenseKey:i,licenseValidationUrl:a,dracoDecoderPath:d,ktx2TranscoderPath:s,meshopt:p,preset:"minimal",showFloorGrid:Cr,showLoadingOverlay:!1,showObjectNavigator:!1,selectedObject:null,zoomOnSelected:!1,highlightOnHover:!1,autoRotate:!1,cinematic:!1,onViewerReady:r})}):null]}),R(wu,{panel:wr,tabs:Qx,tab:ki,onTabChange:Cs,hasModel:!!P,onPointerDownCapture:()=>No("scene"),children:ki==="sequences"?R(Wx,{config:ee,onChange:Rt,controls:wb,bindings:q,clipDetails:Nt.clipDetails}):ki==="clips"?R(qx,{config:Li.config?{...ee,animations:Li.config}:ee,onChange:Li.onChange?r=>Li.onChange?.(r.animations):Rt,clipDetails:At.clipDetails,active:At.active,play:At.play,pause:At.pause,stop:At.stop,setSpeed:At.setSpeed,seek:At.seek}):nt(Eo,"cinematic")?R(Yx,{config:ee,onChange:Rt,cameraState:Ml,onPreviewWaypoint:pl}):R(We,{requiredTier:"starter",feature:"Cinematic"})})]}),Wt.open?ae(et,{children:[R(ii,{orientation:"vertical",label:"Resize inspector",onPointerDown:Wt.startResize,onKeyDown:Wt.onResizeKey}),ae("aside",{className:"bb-panel bb-panel--right",style:{width:Wt.size},onPointerDownCapture:()=>No(ht!=="object"?"scene":"bindings"),children:[ae("div",{className:"bb-inspectorScope",children:[R("div",{className:"bb-scopeSwitch",role:"tablist","aria-label":"What to edit",children:["object","scene","configure"].map(r=>R("button",{type:"button",role:"tab","aria-selected":ht===r,className:ht===r?"is-active":"",onClick:()=>{on(r),No(r==="object"?"bindings":"scene")},children:r==="object"?"Object":r==="scene"?"Scene":"Configure"},r))}),R("button",{type:"button",className:"bb-toolButton bb-toolButton--small","aria-label":"Hide inspector",title:"Hide panel",onClick:()=>Wt.setOpen(!1),children:R($x,{size:14})})]}),ht==="configure"?P?R("section",{className:"bb-editor",children:R(Jx,{config:ee,onChange:Be.setValueAsStep,objectBindings:q,materialVariantGroups:il,selectedKey:L,previewSelections:Ci,onPreviewChange:Rs,onPreviewAsCustomer:()=>Br(!0),publish:t,modelFileName:w})}):R("p",{className:"bb-panelEmpty",children:"Open a model to let customers customise it."}):ht==="scene"?P?ae(et,{children:[R("div",{className:"bb-tabs",role:"tablist","aria-label":"Scene settings",children:Fc.map(r=>R("button",{type:"button",role:"tab","aria-selected":nn===r.id,className:`bb-tab ${nn===r.id?"bb-tab--active":""}`,onClick:()=>Tr(r.id),children:r.label},r.id))}),R("section",{className:"bb-editor",children:R(Na,{diagnostics:{report:tl?.url===P?tl.report:null,runtimeStats:xb,onRefresh:vb,onSelectObject:r=>{let l=Object.keys(q).find(b=>b===r||q[b].modelObjectId===r);l&&oa(l)}},onDiagnosticsOpenChange:hb,config:ee,onChange:Rt,activeSubTab:nn,materialVariantGroups:il,onImageFile:wl,objectBindings:q})})]}):R("p",{className:"bb-panelEmpty",children:"Open a model to edit its scene."}):!Se||!L?R("p",{className:"bb-panelEmpty",children:P?"Select an object to edit it.":"Open a model, then select an object to edit it."}):ae(et,{children:[ae("div",{className:"bb-objectHeader",children:[ae("div",{className:"bb-objectHeaderText",children:[R("h2",{children:Oe&&_e.length>1?`${_e.length} objects`:Se.label||L}),R("code",{title:Oe?void 0:Se.modelObjectId,children:Oe&&_e.length>1?"Edits apply to all of them":Se.id})]}),R(Zn,{icon:R(Lx,{size:14,"aria-hidden":"true"}),title:"Object actions",align:"right",children:r=>ae(et,{children:[ae("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>{r(),Ru({name:Se.label||L,style:kd(Se)})},children:[R(zx,{size:13,"aria-hidden":"true"}),"Copy style"]}),ae("button",{type:"button",className:"bb-headerMenuItem",disabled:!jn,title:jn?`Copied from ${jn.name}`:void 0,onClick:()=>{if(r(),!jn)return;let l=Oe?_e:[L];ie.setValueAsStep(b=>Cd(b,l,jn.style))},children:[R(Ix,{size:13,"aria-hidden":"true"}),"Paste style",Oe&&_e.length>1?` to ${_e.length}`:""]}),ae("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{r(),Bg(Oe&&_e.length>0?_e:[L])},children:[R(Kx,{size:13,"aria-hidden":"true"}),Oe&&_e.length>1?`Delete ${_e.length} objects\u2026`:"Delete object\u2026"]})]})})]}),R("div",{className:"bb-tabs",role:"tablist","aria-label":"Object settings",children:Cu.filter(r=>!Oe||r.group).map(r=>R("button",{type:"button",role:"tab","aria-selected":Lo===r.id,className:`bb-tab ${Lo===r.id?"bb-tab--active":""}`,onClick:()=>Ps(r.id),children:r.label},r.id))}),ae("section",{className:"bb-editor",children:[Lo==="general"&&ae(et,{children:[!Oe&&R(wp,{selectedItem:L,selectedBinding:Se,open:Yt.identity,onToggle:()=>Jt("identity"),updateBinding:wt,idError:Lb}),!Oe&&R(kp,{selectedItem:L,selectedBinding:Se,open:Yt.basics,onToggle:()=>Jt("basics"),updateBinding:wt}),Oe&&R(Ye,{title:"Basics",open:Yt.basics,onToggle:()=>Jt("basics"),children:R("div",{className:"bb-groupFlags",children:["selectable","hoverable","visible"].map(r=>R(Xx,{label:r.charAt(0).toUpperCase()+r.slice(1),values:_e.map(l=>q[l]).filter(l=>l&&!l.removed).map(l=>l[r]!==!1),onChange:l=>ie.setValueAsStep(b=>{let S={...b};for(let k of _e)b[k]&&!b[k].removed&&(S[k]={...b[k],[r]:l});return S})},r))})}),R(jp,{selectedItem:L,selectedBinding:Se,open:Yt.transform,onToggle:()=>Jt("transform"),updateBinding:wt,originalTransform:xt.current[L]??null,originalTransforms:xt.current}),!Oe&&R(Np,{selectedBinding:Se,open:Yt.camera,onToggle:()=>Jt("camera"),cameraState:Pe,formattedCameraState:Eb,savedCameraPosition:mo,onSaveCameraPosition:wg,onGoToSavedCamera:Sg,onClearSavedCamera:kg,onResetView:Sl,onFitScene:Kn})]}),Lo==="material"&&ae("div",{className:"bb-singleSection",children:[R(yp,{disabled:!L,onApply:r=>L&&Xr(L,l=>({...l,...r}))}),R(xp,{selectedItem:L,selectedMaterial:Wr,pbrWorkflow:Ku,onPbrWorkflowChange:Gu,openMaterialPanels:$u,materialPanelEnabled:qu,onToggleMaterialPanel:_u,onSetMaterialPanelState:Fb,updateSelectedMaterial:Xr,setSelectedTexturePath:Db,isTexturePositioningEnabled:pb,onConfirmTexturePosition:Cg,takesImage:bl})]}),Lo==="decals"&&R("div",{className:"bb-singleSection",children:!Oe&&R(Rp,{selectedItem:L,selectedBinding:Se,open:Yt.decals,onToggle:()=>Jt("decals"),updateBinding:wt,placement:xi,onPlacementChange:fg,defaultSize:bg,onImageFile:wl,onNudge:mg})}),Lo==="actions"&&R("div",{className:"bb-singleSection",children:!Oe&&R(Mp,{selectedItem:L,selectedBinding:Se,open:Yt.actions,onToggle:()=>Jt("actions"),updateBinding:wt,takesImage:bl})}),Lo==="data"&&ae(et,{children:[R(Ja,{title:"Metrics",label:"Metrics JSON",open:Yt.metrics,onToggle:()=>Jt("metrics"),draft:Ss,error:Iu,example:'{"area": 42}',onDraftChange:vi,onCommit:()=>yl("metrics",Ss,wi)}),R(Ja,{title:"Metadata",label:"Metadata JSON",open:Yt.metadata,onToggle:()=>Jt("metadata"),draft:ks,error:zu,example:'{"room": "kitchen"}',onDraftChange:yi,onCommit:()=>yl("metadata",ks,Si)})]})]})]}),Bs?R(sp,{scope:ht==="object"?"object":"scene",selectedKey:L,selectedBinding:Se??null,sceneConfig:ee,sceneTab:ht==="configure"?"product":nn,onClose:()=>kr(!1)}):null]})]}):R("button",{type:"button",className:"bb-panelReveal bb-panelReveal--right","aria-label":"Show inspector",title:"Show panel",onClick:()=>Wt.setOpen(!0),children:R(Ux,{size:14})})]}),R(ep,{saveState:Fi&&P?"Saved in this browser":void 0,objectCount:Ht.filter(r=>!q[r]?.removed).length,selectedCount:Oe?_e.length:L?1:0,path:bn.path,hints:ev}),R(np,{toast:Eu,onDismiss:ju}),bn.menu?R(Qc,{...bn.menu,onClose:bn.closeMenu}):null,Fu?R(cp,{commands:Dg(),onClose:()=>Mr(!1)}):null,Hu?R(pp,{onClose:()=>Pr(!1)}):null]}),Xu&&R(su,{target:Dn,onCancel:$i,onConfirm:Pg}),Ao&&R(lu,{models:[{name:Ao.session.model.name,mergedCount:Ao.session.mergeModels?.length??0},...(Ao.session.parkedModels??[]).map(r=>({name:r.model.name,mergedCount:r.mergeModels?.length??0}))],savedAt:Ao.session.savedAt,onCancel:Ng,onConfirm:()=>{let{name:r}=Ao.session.model;Cl().catch(l=>{console.warn("[BindingBuilder] Could not restore the session:",l),W(ms(r)),X("error")})}}),Zu&&R(cu,{destinations:Vn.filter(r=>r.kind==="model"),onCancel:Xb,onChoose:Zb}),Qu&&R(pu,{options:Vn,onCancel:qb,onRemoveModel:Wb,onRemoveMerge:Yb,permanent:!!c,onRemoveAll:c?void 0:()=>{rn(!1),Hi()}}),uo&&R(du,{nodeLabel:uo.length===1?q[uo[0]]?.label||uo[0]:`${uo.length} objects`,count:uo.length,onCancel:Tg,onConfirm:Rg})]})}export{er as a,xv as b,tv as c};
|