@liveroom-tech/react-immersive 6.2.1 → 6.2.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.
Files changed (66) hide show
  1. package/dist/AnimationsTab-IKAAKT3P.mjs +1 -0
  2. package/dist/AnnotationsTab-NEJIXCOM.mjs +1 -0
  3. package/dist/CinematicTab-TIQXCPFE.mjs +1 -0
  4. package/dist/ConfigureTab-NYRMOFW4.mjs +6 -0
  5. package/dist/RulesTab-2U4MFYOZ.mjs +1 -0
  6. package/dist/SequencesTab-LTMJTB76.mjs +1 -0
  7. package/dist/SequencesTab-O7USMDFP.css +1 -0
  8. package/dist/{StreamingTilesModel-6Z7SIC2J.mjs → StreamingTilesModel-IM2DDWO5.mjs} +1 -1
  9. package/dist/binding-builder.css +1 -1
  10. package/dist/binding-builder.d.mts +3 -3
  11. package/dist/binding-builder.d.ts +3 -3
  12. package/dist/binding-builder.js +45 -45
  13. package/dist/binding-builder.mjs +1 -1
  14. package/dist/{chunk-25WC5KDO.mjs → chunk-2LGQKX6Z.mjs} +1 -1
  15. package/dist/chunk-37QOMZW6.mjs +1 -0
  16. package/dist/chunk-3PLML3PO.mjs +1 -0
  17. package/dist/chunk-5C4H7SRF.mjs +1 -0
  18. package/dist/chunk-IT2PUTJS.mjs +1 -0
  19. package/dist/chunk-LEOHZ5HM.mjs +69 -0
  20. package/dist/chunk-RSUXTWM6.mjs +1 -0
  21. package/dist/{chunk-3OCHN3CA.mjs → chunk-SOAUR4DL.mjs} +1 -1
  22. package/dist/chunk-SXN3YYD3.mjs +1 -0
  23. package/dist/chunk-WU3SQZGD.mjs +3 -0
  24. package/dist/{chunk-UTVFRMYW.mjs → chunk-XKJQC3N5.mjs} +2 -2
  25. package/dist/exportSceneMesh-MSQIMBFF.mjs +1 -0
  26. package/dist/hosted.css +1 -1
  27. package/dist/hosted.d.mts +5 -3
  28. package/dist/hosted.d.ts +5 -3
  29. package/dist/hosted.js +44 -44
  30. package/dist/hosted.mjs +1 -1
  31. package/dist/index.css +1 -1
  32. package/dist/index.d.mts +4 -4
  33. package/dist/index.d.ts +4 -4
  34. package/dist/index.js +42 -42
  35. package/dist/index.mjs +1 -1
  36. package/dist/{modelFileResolver-CVmON8hg.d.mts → modelFileResolver-Bq4pW9vc.d.mts} +39 -29
  37. package/dist/{modelFileResolver-CVmON8hg.d.ts → modelFileResolver-Bq4pW9vc.d.ts} +39 -29
  38. package/dist/{modelViewerProps-CIY4nsNY.d.mts → modelViewerProps-BnrJO5DK.d.ts} +2 -1
  39. package/dist/{modelViewerProps-BBnZTFO-.d.ts → modelViewerProps-wjBT4fks.d.mts} +2 -1
  40. package/dist/{publicProps-BARVwXu7.d.ts → publicProps-BZPMIRwj.d.ts} +1 -1
  41. package/dist/{publicProps-n0Yvr_Km.d.mts → publicProps-CW5X_HFh.d.mts} +1 -1
  42. package/dist/simple-model-viewer.css +1 -1
  43. package/dist/simple-model-viewer.d.mts +2 -2
  44. package/dist/simple-model-viewer.d.ts +2 -2
  45. package/dist/simple-model-viewer.js +5 -5
  46. package/dist/simple-model-viewer.mjs +1 -1
  47. package/dist/utils.d.mts +4 -4
  48. package/dist/utils.d.ts +4 -4
  49. package/dist/utils.js +1 -1
  50. package/dist/utils.mjs +1 -1
  51. package/package.json +1 -1
  52. package/dist/AnimationsTab-NUJTEMZ5.mjs +0 -1
  53. package/dist/AnnotationsTab-OHRVWRKI.mjs +0 -1
  54. package/dist/CinematicTab-IJAY2BS6.mjs +0 -1
  55. package/dist/ConfigureTab-UQRRATCY.mjs +0 -6
  56. package/dist/RulesTab-YVBZGJZX.mjs +0 -1
  57. package/dist/SequencesTab-IC5LWQ6N.css +0 -1
  58. package/dist/SequencesTab-VZKEKAUG.mjs +0 -1
  59. package/dist/chunk-7OVEHDDE.mjs +0 -1
  60. package/dist/chunk-AL6UIGWP.mjs +0 -1
  61. package/dist/chunk-KYXJG3TX.mjs +0 -1
  62. package/dist/chunk-LD7QWHB4.mjs +0 -3
  63. package/dist/chunk-RKDATTUM.mjs +0 -1
  64. package/dist/chunk-UHRJ2RBF.mjs +0 -1
  65. package/dist/chunk-YKDDNX2D.mjs +0 -69
  66. package/dist/exportSceneMesh-YJFOLFHS.mjs +0 -1
@@ -1,3 +0,0 @@
1
- import{a as Ld,b as Fd}from"./chunk-E24EFHB5.mjs";import{a as Rn}from"./chunk-FXV4CLAK.mjs";import{a as Bn,b as Tn,c as co,d as jd,e as Sa,g as ie,h as de,i as Id,j as zd,k as j,l as he,m as pt,n as Dd,o as ht,p as xt,q as Jo}from"./chunk-AL6UIGWP.mjs";import{a as ma,c as id,d as rr,e as pd,h as md,i as fd,j as hd,k as xd,l as vd,m as yd,n as wd,o as Sd,p as ya,q as kd,r as Md,t as Pd,u as Bd,v as Ed}from"./chunk-YKDDNX2D.mjs";import{a as ld,b as va,c as st,d as dd,e as Tt,f as Yo,g as cd,h as lt,i as Ye}from"./chunk-FGAJ2UT7.mjs";import{e as ad,f as sd,h as xa}from"./chunk-3OCHN3CA.mjs";import{N as bd,i as ga,k as Po,x as or,y as rd}from"./chunk-UTVFRMYW.mjs";import{a as ud}from"./chunk-37YITTIK.mjs";import{b as od}from"./chunk-2AJK643D.mjs";import{$ as Mn,B as Qi,Ba as ar,C as qo,Ca as gd,Da as Cd,Ea as wa,F as Wo,Fa as Td,G as Gl,Ga as Rd,H as ql,Ha as Nd,I as Wl,Ia as Ad,Ja as Od,Y as er,a as Xi,ca as Zl,e as ei,n as Dl,p as Ll,pa as fa,q as Fl,qa as nr,r as Hl,ra as ir,s as $l,t as Ul,ta as ha,u as Vl,ua as nd,v as oi,w as _l,x as Mo,y as Kl,za as ni}from"./chunk-25WC5KDO.mjs";import{e as Zi}from"./chunk-LX3GXQNU.mjs";import{p as tr}from"./chunk-7JCFNZJM.mjs";import{h as Cn,i as Wt,j as Ht,k as ti}from"./chunk-UHRJ2RBF.mjs";import{b as ed,e as td}from"./chunk-KFLS7GI6.mjs";import{c as Yl,d as Jl,g as Xl,h as ba}from"./chunk-BNKTI3CY.mjs";import{e as Ql}from"./chunk-UCD76KQ6.mjs";import{a as Pn}from"./chunk-TUYVYSN5.mjs";function Bo(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 et(e,o){return{...e,model:{...e.model,activeVariants:o?.activeVariants??[]},annotations:o?.annotations??[],animations:o?.animations??Mo.animations,measurements:o?.measurements,selectionSets:o?.selectionSets,product:o?.product,sequences:o?.sequences}}function $d(e){if(e===void 0)return!0;try{return tr(e),!0}catch{return!1}}function Ud(e){if(e===void 0)return!0;try{return Mn(e),!0}catch{return!1}}function Vd(e){if(e===void 0)return!0;try{return er(e),!0}catch{return!1}}var Qg="react-immersive:binding-builder",em=2,To="session",Ro="model",No="textures",Ca="current",_d=1;function Yt(e){return e.kind==="file"?`file:${e.key}`:`url:${e.url}`}var Xo=null;function ii(){return Xo||(Xo=new Promise((e,o)=>{if(typeof indexedDB>"u"){o(new Error("IndexedDB is not available in this environment."));return}let i=indexedDB.open(Qg,em);i.onupgradeneeded=()=>{let r=i.result;r.objectStoreNames.contains(To)||r.createObjectStore(To),r.objectStoreNames.contains(Ro)||r.createObjectStore(Ro),r.objectStoreNames.contains(No)||r.createObjectStore(No)},i.onsuccess=()=>{let r=i.result;r.onversionchange=()=>{r.close(),Xo=null},e(r)},i.onerror=()=>o(i.error??new Error("Failed to open IndexedDB."))}),Xo.catch(()=>{Xo=null}),Xo)}function Nn(e){return new Promise((o,i)=>{e.oncomplete=()=>o(),e.onerror=()=>i(e.error??new Error("IndexedDB transaction failed.")),e.onabort=()=>i(e.error??new Error("IndexedDB transaction aborted."))})}function Ma(e){return new Promise((o,i)=>{e.onsuccess=()=>o(e.result),e.onerror=()=>i(e.error??new Error("IndexedDB request failed."))})}function ut(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Pa(e){return!ut(e)||typeof e.name!="string"?!1:e.kind==="file"?typeof e.key=="string":e.kind==="url"?typeof e.url=="string":!1}function Kd(e){return ut(e)&&Pa(e.model)&&typeof e.namePrefix=="string"}function tm(e){if(e===void 0)return!0;try{return Kl(e),!0}catch{return!1}}function Gd(e){if(e===void 0)return!0;try{return Zi(e),!0}catch{return!1}}function om(e){return!ut(e)||!Pa(e.model)||!ut(e.bindings)||!ut(e.originalTransforms)||e.modelSettings!==void 0&&(!ut(e.modelSettings)||!Array.isArray(e.modelSettings.annotations)||!ut(e.modelSettings.animations)||!Array.isArray(e.modelSettings.animations.clips)||e.modelSettings.activeVariants!==void 0&&(!Array.isArray(e.modelSettings.activeVariants)||!e.modelSettings.activeVariants.every(o=>typeof o=="string")))||ut(e.modelSettings)&&!Vd(e.modelSettings.measurements)||ut(e.modelSettings)&&!Ud(e.modelSettings.selectionSets)||ut(e.modelSettings)&&!$d(e.modelSettings.product)||ut(e.modelSettings)&&!Gd(e.modelSettings.sequences)?!1:e.mergeModels===void 0?!0:Array.isArray(e.mergeModels)&&e.mergeModels.every(Kd)}function sr(e){if(!ut(e)||e.version!==_d)return!1;if(e.composition!==void 0)try{Wo(e.composition)}catch{return!1}return!(typeof e.savedAt!="number"||!ut(e.bindings)||!ut(e.sceneConfig)||!Pa(e.model)||!Vd(e.sceneConfig.measurements)||!Ud(e.sceneConfig.selectionSets)||!$d(e.sceneConfig.product)||!Gd(e.sceneConfig.sequences)||!tm(e.sceneConfig.section)||e.parkedModels!==void 0&&(!Array.isArray(e.parkedModels)||!e.parkedModels.every(om))||e.mergeModels!==void 0&&(!Array.isArray(e.mergeModels)||!e.mergeModels.every(Kd))||e.modelOrder!==void 0&&(!Array.isArray(e.modelOrder)||!e.modelOrder.every(o=>typeof o=="string")))}function ka(e,o){return e.kind==="url"?Promise.resolve(null):Ma(o.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 qd(e,o){let i=await ii(),r={...e,version:_d,savedAt:Date.now()},t=i.transaction([To,Ro],"readwrite"),n=Nn(t);t.objectStore(To).put(r,Ca);let c=t.objectStore(Ro),s=new Set,p=u=>{u.kind==="file"&&s.add(u.key)};p(r.model),r.mergeModels?.forEach(u=>p(u.model)),r.parkedModels?.forEach(u=>{p(u.model),u.mergeModels?.forEach(h=>p(h.model))});for(let{key:u,file:h}of o??[]){let m={key:u,blob:h,name:h.name,type:h.type,lastModified:h.lastModified};c.put(m,u)}let f=c.getAllKeys();return f.onsuccess=()=>{for(let u of f.result)s.has(u)||c.delete(u)},await n,r}function Hd(e,o){return Promise.all(e.map(async i=>({entry:i,file:await ka(i.model,o)})))}async function Wd(){let e=await ii(),o=e.transaction(To,"readonly"),i=Nn(o),r=await Ma(o.objectStore(To).get(Ca));if(await i,!sr(r))return null;let t=r.parkedModels??[],n=r.mergeModels??[],c=e.transaction(Ro,"readonly"),s=Nn(c),p=c.objectStore(Ro),[f,u,h]=await Promise.all([ka(r.model,p),Hd(n,p),Promise.all(t.map(async m=>({entry:m,file:await ka(m.model,p),mergeFiles:await Hd(m.mergeModels??[],p)})))]);return await s,r.model.kind==="file"&&!f?null:{session:{...r,parkedModels:t,mergeModels:n},file:f,parkedFiles:h,mergeFiles:u}}async function Yd(){let o=(await ii()).transaction([To,Ro,No],"readwrite"),i=Nn(o);o.objectStore(To).delete(Ca),o.objectStore(Ro).clear(),o.objectStore(No).clear(),await i}async function An(e,o){let r=(await ii()).transaction(No,"readwrite"),t=Nn(r),n={blob:o,name:o.name,type:o.type,savedAt:Date.now()};r.objectStore(No).put(n,e),await t}async function po(e){let i=(await ii()).transaction(No,"readonly"),r=Nn(i),t=await Ma(i.objectStore(No).get(e));return await r,t?new File([t.blob],t.name,{type:t.type,lastModified:t.savedAt}):null}function Qo(e){return`url:${e}`}function Ta(e){return e.models.find(o=>!e.composition.placements[Qo(o.url)]?.deleted)??e.models[0]}function Ra(e){return Wo(e.composition)}function dr(e,o){return et(e,o.modelSettings)}function nm(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 On(e){return(e.mergeModels??[]).map(nm)}function Na(e){let o=e.name??"model";return{url:e.url,name:o,bindings:e.objectBindings,originalTransforms:{},sessionModel:{kind:"url",url:e.url,name:o},mergedModelSources:On(e),modelSettings:e.modelSettings}}function Aa(e){let o=new Map;for(let i of e.models){let{url:r,name:t,assetId:n,tilesetUrl:c,assetVersion:s}=i;o.set(r,{url:r,name:t,assetId:n,tilesetUrl:c,assetVersion:s});for(let p of i.mergeModels??[])o.set(p.url,{url:p.url,assetId:p.assetId})}return o}function Jd(e){let o=r=>r.map(t=>({url:t.url,assetId:e.sources.get(t.url)?.assetId??null,namePrefix:t.namePrefix})),i=e.modelOrder.flatMap(r=>{if(e.composition.placements[Qo(r)]?.deleted)return[];let t=e.sources.get(r)??{url:r};if(r===e.modelUrl)return[{...t,url:r,name:e.modelName,objectBindings:e.bindings,mergeModels:o(e.mergedModelSources),modelSettings:Bo(e.sceneConfig)}];let n=e.parkedModels.find(c=>c.url===r);return n?[{...t,url:r,name:n.name,objectBindings:n.bindings,mergeModels:o(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(([,r])=>!r.deleted))},sceneConfig:et(e.sceneConfig)}}function Ba(e){return JSON.stringify(e,(o,i)=>i&&typeof i=="object"&&!Array.isArray(i)?Object.fromEntries(Object.entries(i).sort(([r],[t])=>r<t?-1:r>t?1:0)):i)}function cr(e,o){return e===o||Ba(e)===Ba(o)}function im(e){return Bo(et(Mo,e))}function En(e){return Ba({models:e.models.map(o=>({url:o.url,name:o.name,objectBindings:o.objectBindings,mergeModels:(o.mergeModels??[]).map(({url:i,namePrefix:r})=>({url:i,namePrefix:r})),modelSettings:im(o.modelSettings)})),composition:e.composition,sceneConfig:et(e.sceneConfig)})}function Vv(e){if(!(e.models.length<2))return e.models.flatMap(o=>{let i=e.composition.placements[Qo(o.url)]??{};return i.deleted?[]:[{url:o.url,label:i.label??o.name,transform:i,visible:i.visible!==!1,objectBindings:o.objectBindings,sceneConfig:dr(e.sceneConfig,o),mergeModels:o.mergeModels?.map(({url:r,namePrefix:t})=>({url:r,namePrefix:t}))}]})}var Xd=new Set(["path","image","url","poster","src","imageUrl"]);function rm(e){return e.startsWith("blob:")||e.startsWith("data:")||!!Wt(e)}function Zo(e,o=new Set){if(Array.isArray(e))e.forEach(i=>Zo(i,o));else if(e&&typeof e=="object")for(let[i,r]of Object.entries(e))typeof r=="string"?Xd.has(i)&&rm(r)&&o.add(r):Zo(r,o);return o}function lr(e,o){return Array.isArray(e)?e.map(i=>lr(i,o)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([i,r])=>[i,typeof r=="string"&&Xd.has(i)&&o.has(r)?o.get(r):lr(r,o)])):e}async function Zd(e){let o=Wt(e)??e,i=await(await fetch(o)).blob(),r=e.startsWith("blob:")||e.startsWith("data:")?"image":e.split("/").pop()||"image";return new File([i],r,{type:i.type})}async function Qd(e,o){let i=u=>e.session.composition?.placements[Yt(u)]?.deleted;e={...e,parkedFiles:e.parkedFiles.filter(u=>!i(u.entry.model))};let r=new Map,t=async(u,h)=>{if(u.kind!=="file")return u;if(!h)throw new Error(`The scene bundle is missing ${u.name}.`);let{url:m}=await o(h);return r.set(`file:${u.key}`,Qo(m)),{kind:"url",url:m,name:u.name}},n=async u=>{let h=[];for(let{entry:m,file:C}of u)h.push({entry:{...m,model:await t(m.model,C)},file:null});return h},c=await t(e.session.model,e.file),s=await n(e.mergeFiles),p=[];for(let u of e.parkedFiles){let h=await t(u.entry.model,u.file),m=await n(u.mergeFiles);p.push({entry:{...u.entry,model:h,mergeModels:m.map(C=>C.entry)},file:null,mergeFiles:m})}let f=e.session.composition;return{file:null,mergeFiles:s,parkedFiles:p,session:{...e.session,model:c,mergeModels:s.map(u=>u.entry),parkedModels:p.map(u=>u.entry),modelOrder:e.session.modelOrder?.map(u=>r.get(u)??u),composition:f&&{...f,placements:Object.fromEntries(Object.entries(f.placements).map(([u,h])=>[r.get(u)??u,h]))}}}}import{strFromU8 as am,strToU8 as sm,unzip as lm}from"fflate";var ri=512*1024*1024,ec=5*1024*1024;function Oa(e){return[e.model,...(e.mergeModels??[]).map(o=>o.model),...(e.parkedModels??[]).flatMap(o=>[o.model,...(o.mergeModels??[]).map(i=>i.model)])]}function tc(e){let o=t=>t.kind==="file"?`/bundle/${encodeURIComponent(t.key)}.glb`:t.url,i=[{model:e.model,bindings:e.bindings,merges:e.mergeModels,config:e.sceneConfig},...(e.parkedModels??[]).map(t=>({model:t.model,bindings:t.bindings,merges:t.mergeModels,config:et(e.sceneConfig,t.modelSettings)}))],r=i.map(t=>t.model.kind==="file"?`file:${t.model.key}`:`url:${t.model.url}`);if(new Set(r).size!==r.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(t=>!r.includes(t))))throw new Error("Invalid scene asset order.");for(let t of e.parkedModels??[])for(let n of Object.values(t.originalTransforms))for(let c of["position","rotation","scale"]){let s=n?.[c];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 t of i)Zl({version:1,objectBindings:t.bindings,configuration:{modelUrl:o(t.model),sceneConfig:t.config,mergeModels:t.merges?.map(n=>({url:o(n.model),namePrefix:n.namePrefix}))}})}async function oc(e,o){let i=JSON.parse(JSON.stringify({...e,version:1,savedAt:Date.now()})),r={},t=[],n=[],c=0;async function s(m,C){if(c+=C.size,c>ri)throw new Error("Scene bundle exceeds the 512 MiB expanded limit.");r[m]=new Uint8Array(await C.arrayBuffer())}for(let m of Oa(i)){if(m.kind!=="file"||t.some(w=>w.key===m.key))continue;let C=o.get(m.key);if(!C)throw new Error(`Cannot save scene: missing uploaded file ${m.name}.`);let B=`models/${t.length}`;t.push({key:m.key,path:B,name:C.name,type:C.type,lastModified:C.lastModified}),await s(B,C)}let p=new Map;async function f(m,C=0){if(C>64)throw new Error("Scene data is too deeply nested.");if(!(!m||typeof m!="object"))for(let[B,w]of Object.entries(m)){if(["__proto__","prototype","constructor"].includes(B))throw new Error("Reserved scene property.");if(B!=="metadata")if(typeof w=="string"){if(!["path","image","url","poster","src","imageUrl","customEnvironmentUrl"].includes(B))continue;let P=Wt(w),v=P||w.startsWith("blob:")||w.startsWith("data:")?null:await po(w);if(!v&&!P&&!w.startsWith("blob:")&&!w.startsWith("data:"))continue;let d=p.get(w);if(d){m[B]=d;continue}if(!v){let N=await fetch(P??w);if(!N.ok)throw new Error("Cannot read an uploaded texture for this scene.");let A=await N.blob();v=new File([A],`texture-${n.length}`,{type:A.type})}let x=`textures/${n.length}`,b=`/__ri_bundle_texture__/${n.length}`;n.push({ref:b,path:x,name:v.name,type:v.type}),await s(x,v),p.set(w,b),m[B]=b}else await f(w,C+1)}}for(let m of Oa(i))if(m.kind==="url"&&m.url.startsWith("blob:"))throw new Error("Cannot save a temporary model URL without its original file.");if(await f(i),!sr(i))throw new Error("Invalid scene snapshot.");tc(i);let u=sm(JSON.stringify({format:"react-immersive-scene",version:1,session:i,files:t,textures:n}));if(u.byteLength>ec)throw new Error("Scene settings exceed the 5 MiB limit.");if(c+u.byteLength>ri||Object.keys(r).length+1>1024)throw new Error("Scene bundle exceeds its size or file-count limit.");r["scene.json"]=u;let h=await rr(r);if(h.byteLength>ri)throw new Error("Compressed scene bundle exceeds 512 MiB.");return new Blob([h],{type:"application/zip"})}async function nc(e){if(e.size>ri)throw new Error("Scene ZIP exceeds 512 MiB.");let o=0,i=0,r="",t=new Set,n=new Uint8Array(await e.arrayBuffer()),c=await new Promise((w,P)=>lm(n,{filter(v){return o+=v.originalSize,i++,t.has(v.name)?(r="Duplicate scene ZIP entry.",!1):(t.add(v.name),i>1024||o>ri||v.name==="scene.json"&&v.originalSize>ec||!/^(scene\.json|models\/\d+|textures\/\d+)$/.test(v.name)?(r="Invalid or oversized scene ZIP entries.",!1):!0)}},(v,d)=>v?P(v):r?P(new Error(r)):w(d)));if(!c["scene.json"])throw new Error("This ZIP does not contain a React Immersive scene.");let s=JSON.parse(am(c["scene.json"]));if(s.format!=="react-immersive-scene"||s.version!==1||!sr(s.session)||!Array.isArray(s.files)||!Array.isArray(s.textures))throw new Error("Invalid scene bundle manifest.");tc(s.session);let p=new Map,f=new Set;for(let w of s.files){if(!w||typeof w.key!="string"||!/^models\/\d+$/.test(w.path)||!c[w.path]||typeof w.name!="string"||typeof w.type!="string"||!Number.isFinite(w.lastModified)||f.has(w.path)||p.has(w.key))throw new Error("Invalid model file in scene bundle.");f.add(w.path),p.set(w.key,new File([c[w.path]],w.name,{type:w.type,lastModified:w.lastModified}))}for(let w of Oa(s.session))if(w.kind==="file"&&!p.has(w.key))throw new Error(`Scene bundle is missing ${w.name}.`);let u=new Map,h=crypto.randomUUID();for(let w of s.textures){if(!w||typeof w.ref!="string"||!/^\/__ri_bundle_texture__\/\d+$/.test(w.ref)||!/^textures\/\d+$/.test(w.path)||!c[w.path]||typeof w.name!="string"||typeof w.type!="string"||f.has(w.path)||u.has(w.ref))throw new Error("Invalid texture in scene bundle.");f.add(w.path),u.set(w.ref,{path:`materials/scene-${h}/${u.size}`,file:new File([c[w.path]],w.name,{type:w.type})})}function m(w,P=0){if(P>64)throw new Error("Scene data is too deeply nested.");if(!(!w||typeof w!="object"))for(let[v,d]of Object.entries(w)){if(["__proto__","constructor","prototype"].includes(v))throw new Error("Reserved scene property.");if(v!=="metadata")if(typeof d=="string"&&d.startsWith("/__ri_bundle_texture__/")){let x=u.get(d);if(!x)throw new Error("Scene bundle is missing a texture.");if(v==="path")w[v]=x.path;else{let b=c[[...s.textures].find(A=>A.ref===d).path],N="";for(let A=0;A<b.length;A+=32768)N+=String.fromCharCode(...b.subarray(A,A+32768));w[v]=`data:${x.file.type||"application/octet-stream"};base64,${btoa(N)}`}}else m(d,P+1)}}m(s.session),await Promise.all([...u.values()].map(w=>An(w.path,w.file)));let C=w=>w.kind==="file"?p.get(w.key):null,B=w=>w.map(P=>({entry:P,file:C(P.model)}));return{session:s.session,file:C(s.session.model),mergeFiles:B(s.session.mergeModels??[]),parkedFiles:(s.session.parkedModels??[]).map(w=>({entry:w,file:C(w.model),mergeFiles:B(w.mergeModels??[])}))}}import{useCallback as Z,useEffect as Le,useMemo as _e,useRef as re,useState as U}from"react";import{Box3 as zu,Vector3 as nv}from"three";import{Box as iv,ChevronDown as rv,ClipboardPaste as av,Copy as sv,Ellipsis as lv,Eye as dv,PanelLeftClose as cv,PanelLeftOpen as pv,PanelRightClose as uv,PanelRightOpen as bv,Pin as gv,PinOff as mv,Trash2 as fv}from"lucide-react";import{useEffect as dm,useId as cm,useRef as ic,useState as rc}from"react";import{Check as pm,ChevronDown as um,History as bm,ListRestart as gm,Plus as mm,Trash2 as fm,Upload as hm}from"lucide-react";import{Fragment as sc,jsx as bt,jsxs as Rt}from"react/jsx-runtime";function ai({label:e,icon:o,title:i,align:r="left",children:t}){let[n,c]=rc(!1),s=ic(null),p=ic(null),f=cm();return dm(()=>{if(!n)return;let u=m=>{s.current?.contains(m.target)||c(!1)},h=m=>{m.key==="Escape"&&(c(!1),p.current?.focus())};return window.addEventListener("pointerdown",u),window.addEventListener("keydown",h),()=>{window.removeEventListener("pointerdown",u),window.removeEventListener("keydown",h)}},[n]),Rt("div",{className:"bb-headerMenuWrapper",ref:s,children:[Rt("button",{ref:p,type:"button",className:`bb-headerButton ${e?"":"bb-headerButton--icon"} ${n?"bb-headerButton--open":""}`,onClick:()=>c(u=>!u),title:i,"aria-label":e?void 0:i,"aria-expanded":n,"aria-controls":n?f:void 0,children:[o,e?Rt(sc,{children:[e,bt(um,{size:12,"aria-hidden":"true"})]}):null]}),n?bt("div",{id:f,className:`bb-headerMenu bb-headerMenu--${r}`,role:"group","aria-label":i,children:t(()=>c(!1))}):null]})}function ac({models:e,activeModelUrl:o,onSelectModel:i,onRestore:r,onRemove:t,onAddModel:n,onUpload:c,onReset:s,resetLabel:p,restoreDisabled:f,addModelDisabled:u,confirmRemove:h=!0,close:m}){let[C,B]=rc(!1);return C&&t?Rt("div",{className:"bb-headerMenuConfirm",role:"alertdialog","aria-label":"Remove model",children:[bt("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."}),Rt("div",{className:"bb-headerMenuConfirmActions",children:[bt("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>B(!1),children:"Cancel"}),bt("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{m(),t()},autoFocus:!0,children:"Remove"})]})]}):Rt(sc,{children:[e?bt("div",{className:"bb-modelMenuList",role:"radiogroup","aria-label":"Active model",children:e.map(w=>Rt("button",{type:"button",role:"radio","aria-checked":w.url===o,className:"bb-headerMenuItem bb-modelMenuItem",title:w.label,onClick:()=>{m(),i?.(w.url)},children:[bt("span",{className:"bb-modelMenuCheck",children:w.url===o?bt(pm,{size:14,"aria-hidden":"true"}):null}),bt("span",{className:"bb-modelMenuName",children:w.label})]},w.url))}):null,c?Rt("button",{type:"button",className:"bb-headerMenuItem",disabled:u,onClick:()=>{m(),c()},children:[bt(hm,{size:14,"aria-hidden":"true"}),"Open model\u2026"]}):null,n?Rt("button",{type:"button",className:"bb-headerMenuItem",disabled:u,onClick:()=>{m(),n()},title:"Add another model, as a separate model or merged into this one",children:[bt(mm,{size:14,"aria-hidden":"true"}),"Add model\u2026"]}):null,r?Rt("button",{type:"button",className:"bb-headerMenuItem",disabled:f,onClick:()=>{m(),r()},title:"Restore your last session: the model, its object bindings, and scene settings saved in this browser",children:[bt(bm,{size:14,"aria-hidden":"true"}),"Restore last session"]}):null,s?Rt("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>{m(),s()},children:[bt(gm,{size:14,"aria-hidden":"true"}),p]}):null,t?Rt("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{if(h){B(!0);return}m(),t()},children:[bt(fm,{size:14,"aria-hidden":"true"}),"Remove model\u2026"]}):null]})}import{useCallback as xm,useEffect as vm,useMemo as ym,useRef as lc}from"react";import{jsx as Ea,jsxs as wm}from"react/jsx-runtime";function dc({liveViewerRef:e,renderBefore:o,split:i,onSplitChange:r,labels:t,beforeAction:n,report:c,selected:s,onSelect:p,matchBy:f,onMatchByChange:u,showOutlines:h,onShowOutlinesChange:m}){let C=lc(null),B=lc(null),w=ym(()=>Md(),[]);vm(()=>()=>w.detach(),[w]);let P=xm(v=>{B.current=v;let d=e.current;d&&w.attach(0,d.raw.controls,d.invalidate),w.attach(1,v.raw.controls,v.invalidate)},[w,e]);return wm("div",{ref:C,className:"ri-compare ri-compare--overlay",style:{"--ri-compare-split":`${i*100}%`},children:[Ea("div",{className:"ri-compare__layer ri-compare__layer--before",children:o(P)}),c&&Ea(kd,{showOutlines:h,onShowOutlinesChange:m,matchBy:f,onMatchByChange:u,report:c,selected:s,onClear:()=>p?.(null),onSelect:v=>{let d=v.afterObjectId?0:1,x=d===0?e.current:B.current,b=d===0?v.afterObjectId:v.beforeObjectId,N=b?x?.raw.nodes[b]:null;w.setLeader(d),p?.(v),x&&N&&(x.raw.controls.fitToBox(N,!0),x.invalidate())}}),Ea(Pd,{split:i,onSplitChange:r,labels:t,containerRef:C,beforeAction:n})]})}import{useCallback as uo,useEffect as cc,useMemo as pc,useRef as pr,useState as uc}from"react";var Sm={currentClip:null,isPlaying:!1,speed:1,time:0,duration:0,active:[]};function km(e,o){let i=[],r=new Map,t=new Map,n=new Map,c=new Set;for(let s of e){let p=o.get(s);if(!p)continue;let f=p.clipDetails??p.clips.map(h=>({sourceName:h,duration:0}));n.set(s,f);let u=new Map;for(let h of f){let m=h.sourceName;for(let C=2;c.has(m);C+=1)m=`${h.sourceName} (${C})`;c.add(m),i.push({sourceName:m,duration:h.duration}),r.set(m,{url:s,sourceName:h.sourceName}),u.set(h.sourceName,m)}t.set(s,u)}return{clipDetails:i,targets:r,displayNamesByUrl:t,clipDetailsByUrl:n}}function Cm(e,o,i){let r=[];for(let t of e){let n=o.get(t),c=i.get(t);if(!(!n||!c))for(let s of n.active){let p=c.get(s.clip);p&&r.push({...s,clip:p})}}return r}function bc(e){let o=pr(new Map),i=pr(new Map),r=pr(new Map),[t,n]=uc(0),[c,s]=uc(0),p=uo((T,z)=>{if(o.current.get(T)===z)return;r.current.get(T)?.(),r.current.delete(T),o.current.set(T,z),i.current.set(T,z.getState?.()??Sm);let y=z.subscribe?.(Q=>{i.current.set(T,Q),s(G=>G+1)});y&&r.current.set(T,y),n(Q=>Q+1)},[]);cc(()=>{let T=new Set(e),z=!1;for(let y of[...o.current.keys()])T.has(y)||(r.current.get(y)?.(),r.current.delete(y),o.current.delete(y),i.current.delete(y),z=!0);z&&n(y=>y+1)},[e]),cc(()=>()=>r.current.forEach(T=>T()),[]);let{clipDetails:f,targets:u,displayNamesByUrl:h,clipDetailsByUrl:m,hasModels:C}=pc(()=>({...km(e,o.current),hasModels:o.current.size>0}),[e,t]),B=pr(u);B.current=u;let w=pc(()=>Cm(e,i.current,h),[e,h,c]),P=uo((T,z,y)=>{y(),!z.subscribe&&z.getState&&(i.current.set(T,z.getState()),s(Q=>Q+1))},[]),v=uo(T=>{o.current.forEach((z,y)=>P(y,z,()=>T(z,y)))},[P]),d=uo((T,z)=>{let y=B.current.get(T);if(!y)return;let Q=o.current.get(y.url);Q&&P(y.url,Q,()=>z(Q,y))},[P]),x=uo((T,z)=>d(T,(y,Q)=>y.play(Q.sourceName,z)),[d]),b=uo(T=>T===void 0?v(z=>z.pause()):d(T,(z,y)=>z.pause(y.sourceName)),[v,d]),N=uo(T=>T===void 0?v(z=>z.stop()):d(T,(z,y)=>z.stop(y.sourceName)),[v,d]),A=uo((T,z)=>z===void 0?v(y=>y.setSpeed(T)):d(z,(y,Q)=>y.setSpeed(T,Q.sourceName)),[v,d]),K=uo((T,z)=>z===void 0?v(y=>y.seek?.(T)):d(z,(y,Q)=>y.seek?.(T,Q.sourceName)),[v,d]);return{clipDetails:f,clipDetailsByUrl:m,displayNamesByUrl:h,hasModels:C,active:w,play:x,pause:b,stop:N,setSpeed:A,seek:K,handleModelAnimationsReady:p}}import{useEffect as Tm,useMemo as Rm}from"react";function si(e,o){let i=new Map(e.animations.clips.map(n=>[n.sourceName,n])),r=o.map(({sourceName:n})=>i.get(n)??{sourceName:n,displayName:n,hidden:!1,loopMode:"repeat",speed:1}),t=e.animations.autoplayClip&&r.some(n=>n.sourceName===e.animations.autoplayClip&&!n.hidden)?e.animations.autoplayClip:null;return t===e.animations.autoplayClip&&r.length===e.animations.clips.length&&r.every((n,c)=>n===e.animations.clips[c])?e.animations:{clips:r,autoplayClip:t}}function ur(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function li(e,o){if(!ur(e)||!ur(o))return o??e;let i={...e};for(let[r,t]of Object.entries(o)){if(t===void 0)continue;if(r==="section"){i[r]=Qi(i[r],t);continue}if(r==="sequences"){i[r]=Zi(t);continue}let n=i[r];i[r]=ur(n)&&ur(t)?li(n,t):t}return i}import{useCallback as Ao,useReducer as Mm,useRef as Pm}from"react";var Bm=100;function bo(e,o){switch(o.type){case"history":return o.updater(e);case"set":{let i=typeof o.updater=="function"?o.updater(e.present):o.updater;if(i===e.present)return e;let r=o.track?e.edits+1:e.edits,t=!o.track&&e.edits===0?i:e.baseline;return o.track?o.coalesce?{...e,present:i,future:[],edits:r,baseline:t}:{past:[...e.past,e.present].slice(-Bm),present:i,future:[],edits:r,baseline:t}:{...e,present:i,baseline:t}}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,...r]=e.future;return{...e,past:[...e.past,e.present],present:i,future:r,edits:e.edits+1}}case"reset":return{past:[],present:o.value,future:[],edits:o.track?e.edits+1:0,baseline:o.track?e.baseline:o.value}}}function di(e,o=600){let[i,r]=Mm(bo,{past:[],present:e,future:[],edits:0,baseline:e}),t=Pm(0),n=Ao(C=>{let B=Date.now(),w=B-t.current<o;t.current=B,r({type:"set",updater:C,coalesce:w,track:!0})},[o]),c=Ao(C=>{let B=Date.now()-t.current<o;r({type:"set",updater:C,coalesce:B,track:!1})},[o]),s=Ao(C=>{t.current=0,r({type:"set",updater:C,coalesce:!1,track:!0})},[]),p=Ao(C=>{r({type:"history",updater:C})},[]),f=Ao(C=>{t.current=0,r({type:"history",updater:typeof C=="function"?C:()=>C})},[]),u=Ao(()=>{t.current=0,r({type:"undo"})},[]),h=Ao(()=>{t.current=0,r({type:"redo"})},[]),m=Ao((C,B)=>{t.current=0,r({type:"reset",value:C,track:B?.asEdit??!1})},[]);return{value:i.present,setValue:n,setValueUntracked:c,setValueAsStep:s,updateHistory:p,restoreSnapshot:f,snapshot:i,undo:u,redo:h,reset:m,canUndo:i.past.length>0,canRedo:i.future.length>0,edits:i.edits,baseline:i.baseline}}function Nm(e,o){return e.sourceName===o.sourceName&&e.displayName===o.displayName&&e.hidden===o.hidden&&e.loopMode===o.loopMode&&e.speed===o.speed}function gc(e,o,i,r){let t=et(o,e.modelSettings);if(t.animations===i)return e;let n={...t,animations:i},c=e.sceneHistory??{past:[],present:t,future:[],baseline:t,edits:0};return{...e,modelSettings:Bo(n),sceneHistory:bo(c,{type:"set",updater:n,track:r,coalesce:!1})}}function mc({modelUrl:e,sceneConfig:o,setSceneConfig:i,setSceneConfigUntracked:r,parkedModels:t,setParkedModels:n,animations:c,markSessionEdited:s}){let{clipDetailsByUrl:p,displayNamesByUrl:f}=c;Tm(()=>{let m=e?p.get(e):void 0;m&&r(C=>{let B=si(C,m);return B===C.animations?C:{...C,animations:B}}),n(C=>{let B=!1,w=C.map(P=>{let v=p.get(P.url);if(!v)return P;let d=et(o,P.modelSettings),x=gc(P,o,si(d,v),!1);return B||(B=x!==P),x});return B?w:C})},[p,e,o,r,n]);let u=Rm(()=>{let m=[],C=null;for(let[B,w]of f){let P=B===e?o:et(o,t.find(d=>d.url===B)?.modelSettings),v=si(P,p.get(B)??[]);for(let d of v.clips){let x=w.get(d.sourceName);x&&m.push({...d,sourceName:x,displayName:d.displayName===d.sourceName?x:d.displayName})}C??(C=v.autoplayClip?w.get(v.autoplayClip)??null:null)}return{clips:m,autoplayClip:C}},[f,p,e,o,t]);return{config:u,onChange:m=>{let C=new Map(u.clips.map(P=>[P.sourceName,P])),B=new Map(m.clips.map(P=>[P.sourceName,P])),w=(P,v)=>{let d=f.get(P);if(!d)return v.animations;let x=si(v,p.get(P)??[]),b=x.clips.map(A=>{let K=d.get(A.sourceName),T=K?B.get(K):void 0;if(!T)return A;let z={...T,sourceName:A.sourceName,displayName:T.displayName===C.get(K)?.displayName?A.displayName:T.displayName};return Nm(A,z)?A:z}),N=m.autoplayClip===u.autoplayClip?x.autoplayClip:[...d].find(([,A])=>A===m.autoplayClip)?.[0]??null;return N===x.autoplayClip&&b.every((A,K)=>A===x.clips[K])?x:{clips:b,autoplayClip:N}};e&&i(P=>{let v=w(e,P);return v===P.animations?P:{...P,animations:v}}),n(P=>P.map(v=>gc(v,o,w(v.url,et(o,v.modelSettings)),!0))),s()}}}import{useEffect as Am,useRef as Om,useState as br}from"react";import{ChevronLeft as Em,ChevronRight as jm,FileUp as Im,RotateCcw as zm,X as Dm}from"lucide-react";import{Fragment as Vm,jsx as V,jsxs as He}from"react/jsx-runtime";var Lm="image/png,image/jpeg,image/webp,image/avif,image/gif";function Fm(e){let o=e.trim();return!!(o&&Wt(o))||/^(blob:|data:image\/)/i.test(o)}var Hm=["lit","unlit","normals"],$m=["default","color","image","environment"],Um={pbr:"PBR",matcap:"Matcap","uv-checker":"UV checker"};function fc(e){let o=e%360;return o<0?o+360:o}function hc({config:e,onChange:o,diagnostics:i,onDiagnosticsOpenChange:r,materialVariantGroups:t=[]}){let{model:n,wireframe:c}=e,s=Jl(n),p=t.length>0?s.filter(d=>!t.some(x=>x.variants.some(b=>b.name===d))):[],{tier:f}=lt(),u=ud(),[h,m]=br({orientation:!0,diagnostics:!1,autoRotate:!1,wireframe:!1,section:!1});Am(()=>(r?.(h.diagnostics),()=>r?.(!1)),[h.diagnostics,r]);let C=d=>m(x=>({...x,[d]:!x[d]})),B=d=>o({...e,model:d}),w=d=>o({...e,wireframe:d}),P=e.section??_l,v=d=>o({...e,section:{...P,...d}});return He("div",{className:"se-generalContent",children:[He(ie,{title:"Display",open:h.orientation,onToggle:()=>C("orientation"),children:[He("div",{className:"se-field se-fieldInline",children:[He("div",{className:"se-fieldLabel se-fieldLabel--action",children:[V("span",{children:"Straighten"}),V("button",{type:"button",className:"se-iconButton",onClick:()=>B({...n,rotation:[0,0,0]}),"aria-label":"Reset model rotation",children:V(zm,{size:12})})]}),V("div",{className:"se-axisStepperGrid",children:["X","Y","Z"].map((d,x)=>He("div",{className:"se-axisStepper",children:[V("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let b=[...n.rotation];b[x]=fc(b[x]-90),B({...n,rotation:b})},"aria-label":`Rotate ${d} axis backward`,children:V(Em,{size:12})}),V("span",{className:"se-axisStepperLabel",children:d}),V("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let b=[...n.rotation];b[x]=fc(b[x]+90),B({...n,rotation:b})},"aria-label":`Rotate ${d} axis forward`,children:V(jm,{size:12})})]},d))})]}),V(xt,{label:"Rotation",path:"sceneConfig.model.rotation",value:n.rotation,min:0,max:360,step:1,onChange:d=>B({...n,rotation:d})}),He("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:Hl.map(d=>V("button",{type:"button",className:`se-segmentedOption ${n.renderer===d?"se-segmentedOption--active":""}`,onClick:()=>B({...n,renderer:d}),children:Um[d]},d))})]}),V(pt,{label:"Shading",path:"sceneConfig.model.shading",value:n.shading,options:Hm,onChange:d=>B({...n,shading:d})}),t.length>0&&!st(f,"materialVariants")?V(Ye,{requiredTier:"starter",feature:"Material variants"}):null,(st(f,"materialVariants")?t:[]).map((d,x)=>{let b=s.find(N=>d.variants.some(A=>A.name===N));return He("label",{className:"se-field se-fieldInline",children:[V("span",{className:"se-fieldLabel",children:d.name??"Material variant"}),He("select",{className:"se-select",value:b??"",onChange:N=>{let A=N.target.value,K=s.filter(T=>T!==b);B(ba(n,A?Yl(K,A,t):K))},children:[V("option",{value:"",children:"Model default"}),d.variants.map(N=>V("option",{value:N.name,children:N.label},N.name))]})]},d.name??`group-${x}`)}),p.length>0?He("div",{className:"se-placeholder se-placeholder--spaced",children:["Not in this model: ",p.join(", "),"."," ",V("button",{type:"button",className:"se-linkButton",onClick:()=>B(ba(n,s.filter(d=>!p.includes(d)))),children:"Remove"})]}):null]}),He(ie,{title:"Auto rotate",open:h.autoRotate,onToggle:()=>C("autoRotate"),trailing:V(de,{checked:n.autoRotate??!1,onChange:d=>B({...n,autoRotate:d}),label:"Toggle auto rotate"}),children:[n.autoRotate&&u?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(j,{label:"Speed",path:"sceneConfig.model.autoRotateSpeed",value:n.autoRotateSpeed??1,min:.1,max:3,step:.1,formatValue:d=>`${d.toFixed(1)}x`,onChange:d=>B({...n,autoRotateSpeed:d})}):V("div",{className:"se-placeholder",children:"Enable auto rotate to adjust its speed."})]}),V(ie,{title:"Wireframe",open:h.wireframe,onToggle:()=>C("wireframe"),disabled:!c.enabled,trailing:V(de,{checked:c.enabled,onChange:d=>w({...c,enabled:d}),label:"Toggle wireframe preview"}),children:He(Vm,{children:[V(j,{label:"Opacity",path:"sceneConfig.wireframe.opacity",value:c.opacity,min:0,max:1,step:.01,onChange:d=>w({...c,opacity:d})}),V(ht,{label:"Wire color",path:"sceneConfig.wireframe.color",value:c.color,onChange:d=>w({...c,color:d})})]})}),V(ie,{title:"Section cut",open:h.section,onToggle:()=>C("section"),disabled:!P.enabled,trailing:V(de,{checked:P.enabled,onChange:d=>{v({enabled:d}),d&&m(x=>({...x,section:!0}))},label:"Toggle section cut"}),children:V("div",{"data-ri-path":"sceneConfig.section",children:V(yd,{section:P,onChange:v})})}),i&&V(ie,{title:"Diagnostics",open:h.diagnostics,onToggle:()=>C("diagnostics"),children:V(Ed,{...i})})]})}function xc({config:e,onChange:o}){let{camera:i}=e,[r,t]=br(!0);return V("div",{className:"se-generalContent",children:V(ie,{title:"Lens",open:r,onToggle:()=>t(n=>!n),children:V(j,{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=>o({...e,camera:{...i,fieldOfView:n}})})})})}function vc({config:e,onChange:o,onImageFile:i}){let{background:r,environment:t,groundShadows:n}=e,c=Om(null),[s,p]=br(null),f=Fm(r.imageUrl),{tier:u}=lt(),[h,m]=br({environment:!0,envShadow:!1,background:!0,groundShadows:!1}),C=d=>m(x=>({...x,[d]:!x[d]})),B=d=>o({...e,background:d}),w=d=>o({...e,environment:d}),P=d=>o({...e,groundShadows:d}),v=d=>{if(!d.type.startsWith("image/")){p("Choose a PNG, JPG, WEBP, AVIF or GIF image.");return}p(null);let x=Cn(d);x===r.imageUrl&&Wt(x)||Ht(x,URL.createObjectURL(d)),i?.(x,d),B({...r,imageUrl:x})};return He("div",{className:"se-generalContent",children:[He(ie,{title:"Environment",open:h.environment,onToggle:()=>C("environment"),children:[He("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(d=>V("button",{type:"button",className:`se-segmentedOption ${t.source===d?"se-segmentedOption--active":""}`,onClick:()=>w({...t,source:d}),children:d==="preset"?"Preset":"Custom"},d))})]}),t.source==="preset"?V(pt,{label:"Preset",path:"sceneConfig.environment.preset",value:t.preset,options:$l,onChange:d=>w({...t,source:"preset",preset:d})}):st(u,"customEnvironment")?He("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:t.customEnvironmentUrl,onChange:d=>w({...t,customEnvironmentUrl:d.target.value})}),t.customEnvironmentUrl.trim()&&!Ll(t.customEnvironmentUrl)?V("span",{className:"bb-note bb-note--error se-fieldFull",children:"Use an HDR, EXR, JPG, PNG, or WEBP URL."}):null]}):V(Ye,{requiredTier:"starter",feature:"Custom environments"}),V(j,{label:"Intensity",path:"sceneConfig.environment.intensity",value:t.intensity,min:0,max:3,step:.05,onChange:d=>w({...t,intensity:d})}),V(j,{label:"Rotation",path:"sceneConfig.environment.rotation",value:t.rotation,min:0,max:360,step:1,formatValue:d=>`${d}\xB0`,onChange:d=>w({...t,rotation:d})}),V(he,{label:"As background",path:"sceneConfig.background.type",checked:r.enabled&&r.type==="environment",onChange:d=>B(d?{...r,enabled:!0,type:"environment"}:{...r,type:"color"})}),V("p",{className:"bb-note se-fieldFull",children:"It always lights the model; this also draws it behind."})]}),He(ie,{title:"Environment shadow",open:h.envShadow,onToggle:()=>C("envShadow"),disabled:!t.shadowLight.enabled,trailing:V(de,{checked:t.shadowLight.enabled,onChange:d=>w({...t,shadowLight:{...t.shadowLight,enabled:d}}),label:"Toggle environment shadow light"}),children:[V(j,{label:"Light intensity",path:"sceneConfig.environment.shadowLight.intensity",value:t.shadowLight.intensity,min:0,max:20,step:.1,onChange:d=>w({...t,shadowLight:{...t.shadowLight,intensity:d}})}),V(j,{label:"Shadow bias",path:"sceneConfig.environment.shadowLight.bias",value:t.shadowLight.bias,min:-.01,max:.01,step:1e-4,onChange:d=>w({...t,shadowLight:{...t.shadowLight,bias:d}})})]}),He(ie,{title:"Background",open:h.background,onToggle:()=>C("background"),children:[V(pt,{label:"Show",path:"sceneConfig.background.type",value:r.enabled?r.type:"default",options:$m,onChange:d=>B(d==="default"?{...r,enabled:!1}:{...r,enabled:!0,type:d})}),r.enabled?r.type==="image"&&!st(u,"backgroundImages")?V(Ye,{requiredTier:"starter",feature:"Background images"}):r.type==="image"?He("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"}),He("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:r.imageUrl,readOnly:f,onChange:d=>{p(null),B({...r,imageUrl:d.target.value})}}),f?V("button",{type:"button",className:"bb-fileFieldButton",onClick:()=>B({...r,imageUrl:""}),"aria-label":"Remove uploaded background image",title:"Remove uploaded image",children:V(Dm,{size:13})}):V("button",{type:"button",className:"bb-fileFieldButton",onClick:()=>c.current?.click(),"aria-label":"Upload background image",title:"Upload image",children:V(Im,{size:13})}),V("input",{ref:c,type:"file",accept:Lm,className:"bb-hiddenInput",onChange:d=>{let x=d.target.files?.[0];d.target.value="",x&&v(x)}})]}),s?V("span",{className:"bb-note bb-note--error se-fieldFull",children:s}):f?V("span",{className:"bb-note se-fieldFull",children:"Uploaded files are bundled into the scene export."}):null]}):null:null,r.enabled&&r.type==="color"?V(ht,{label:"Color",path:"sceneConfig.background.color",value:r.color,onChange:d=>B({...r,color:d})}):null]}),He(ie,{title:"Ground shadows",open:h.groundShadows,onToggle:()=>C("groundShadows"),disabled:!n.enabled,trailing:V(de,{checked:n.enabled,onChange:d=>P({...n,enabled:d}),label:"Toggle ground shadows"}),children:[V(j,{label:"Intensity",path:"sceneConfig.groundShadows.intensity",value:n.intensity,min:0,max:1,step:.01,onChange:d=>P({...n,intensity:d})}),V(j,{label:"Border fade",path:"sceneConfig.groundShadows.borderFade",value:n.borderFade,min:0,max:10,step:.1,onChange:d=>P({...n,borderFade:d})}),V(j,{label:"Height",path:"sceneConfig.groundShadows.height",value:n.height,min:-5,max:5,step:.1,onChange:d=>P({...n,height:d})}),V(j,{label:"Size",path:"sceneConfig.groundShadows.size",value:n.size,min:1,max:50,step:.5,onChange:d=>P({...n,size:d})})]})]})}import{useEffect as Km,useRef as Gm,useState as gr}from"react";import{Lock as qm,Plus as Wm}from"lucide-react";import{jsx as pe,jsxs as jn}from"react/jsx-runtime";var _m=["linear","reinhard","aces"];function yc({pp:e,set:o,open:i,toggle:r}){let{colorAverage:t}=e;return pe(ie,{title:"Color average",tooltip:"Blends the frame toward a single average color for a washed-out stylized look.",open:i.colorAverage,onToggle:()=>r("colorAverage"),disabled:!t.enabled,trailing:pe(de,{checked:t.enabled,onChange:n=>o("colorAverage",{...t,enabled:n}),label:"Toggle color average"}),children:pe("div",{className:"se-placeholder",children:"Averages the frame color using the docs default blend mode."})})}function wc({pp:e,set:o,open:i,toggle:r}){let{brightnessContrast:t}=e;return jn(ie,{title:"Brightness and contrast",tooltip:"Raises or lowers overall brightness and contrast across the scene.",open:i.brightnessContrast,onToggle:()=>r("brightnessContrast"),disabled:!t.enabled,trailing:pe(de,{checked:t.enabled,onChange:n=>o("brightnessContrast",{...t,enabled:n}),label:"Toggle brightness contrast"}),children:[pe(j,{path:"sceneConfig.postProcessing.brightnessContrast.brightness",label:"Brightness",value:t.brightness,min:-1,max:1,step:.01,onChange:n=>o("brightnessContrast",{...t,brightness:n})}),pe(j,{path:"sceneConfig.postProcessing.brightnessContrast.contrast",label:"Contrast",value:t.contrast,min:-1,max:1,step:.01,onChange:n=>o("brightnessContrast",{...t,contrast:n})})]})}function Sc({pp:e,set:o,open:i,toggle:r}){let{hueSaturation:t}=e;return jn(ie,{title:"Hue and saturation",tooltip:"Shifts the hue and saturation to tint the whole image.",open:i.hueSaturation,onToggle:()=>r("hueSaturation"),disabled:!t.enabled,trailing:pe(de,{checked:t.enabled,onChange:n=>o("hueSaturation",{...t,enabled:n}),label:"Toggle hue saturation"}),children:[pe(j,{path:"sceneConfig.postProcessing.hueSaturation.hue",label:"Hue",value:t.hue,min:-Math.PI,max:Math.PI,step:.01,formatValue:n=>`${n.toFixed(2)} rad`,onChange:n=>o("hueSaturation",{...t,hue:n})}),pe(j,{path:"sceneConfig.postProcessing.hueSaturation.saturation",label:"Saturation",value:t.saturation,min:-1,max:1,step:.01,onChange:n=>o("hueSaturation",{...t,saturation:n})})]})}function kc({pp:e,set:o,open:i,toggle:r}){let{vignette:t}=e;return jn(ie,{title:"Vignette",tooltip:"Darkens the edges of the screen so the center feels more focused.",open:i.vignette,onToggle:()=>r("vignette"),disabled:!t.enabled,trailing:pe(de,{checked:t.enabled,onChange:n=>o("vignette",{...t,enabled:n}),label:"Toggle vignette"}),children:[pe(j,{path:"sceneConfig.postProcessing.vignette.offset",label:"Offset",value:t.offset,min:0,max:1,step:.01,onChange:n=>o("vignette",{...t,offset:n})}),pe(j,{path:"sceneConfig.postProcessing.vignette.darkness",label:"Darkness",value:t.darkness,min:0,max:1,step:.01,onChange:n=>o("vignette",{...t,darkness:n})}),pe(he,{path:"sceneConfig.postProcessing.vignette.eskil",label:"Eskil",checked:t.eskil,onChange:n=>o("vignette",{...t,eskil:n})})]})}function Cc({pp:e,set:o,open:i,toggle:r}){let{bloom:t}=e;return jn(ie,{title:"Bloom",tooltip:"Makes bright areas glow and bleed softly into nearby pixels.",open:i.bloom,onToggle:()=>r("bloom"),disabled:!t.enabled,trailing:pe(de,{checked:t.enabled,onChange:n=>o("bloom",{...t,enabled:n}),label:"Toggle bloom"}),children:[pe(j,{path:"sceneConfig.postProcessing.bloom.luminanceThreshold",label:"Threshold",value:t.luminanceThreshold,min:0,max:1,step:.01,onChange:n=>o("bloom",{...t,luminanceThreshold:n})}),pe(j,{path:"sceneConfig.postProcessing.bloom.luminanceSmoothing",label:"Smoothing",value:t.luminanceSmoothing,min:0,max:1,step:.01,onChange:n=>o("bloom",{...t,luminanceSmoothing:n})}),pe(j,{path:"sceneConfig.postProcessing.bloom.intensity",label:"Intensity",value:t.intensity,min:0,max:3,step:.05,onChange:n=>o("bloom",{...t,intensity:n})}),pe(he,{path:"sceneConfig.postProcessing.bloom.mipmapBlur",label:"Mipmap blur",checked:t.mipmapBlur,onChange:n=>o("bloom",{...t,mipmapBlur:n})}),pe(j,{path:"sceneConfig.postProcessing.bloom.radius",label:"Radius",value:t.radius,min:0,max:1,step:.01,onChange:n=>o("bloom",{...t,radius:n})}),pe(j,{path:"sceneConfig.postProcessing.bloom.levels",label:"Levels",value:t.levels,min:1,max:16,step:1,onChange:n=>o("bloom",{...t,levels:n})})]})}function Mc({pp:e,set:o,open:i,toggle:r}){let{toneMapping:t}=e;return jn(ie,{title:"Tone mapping",tooltip:"Remaps HDR lighting to screen output and controls exposure style.",open:i.toneMapping,onToggle:()=>r("toneMapping"),disabled:!t.enabled,trailing:pe(de,{checked:t.enabled,onChange:n=>o("toneMapping",{...t,enabled:n}),label:"Toggle tone mapping"}),children:[jn("div",{className:"se-field",children:[pe("span",{className:"se-fieldLabel",children:"Mode"}),pe("div",{className:"se-segmentedControl",children:_m.map(n=>pe("button",{type:"button",className:`se-segmentedOption ${t.mode===n?"se-segmentedOption--active":""}`,onClick:()=>o("toneMapping",{...t,mode:n}),children:n==="aces"?"Filmic":n.charAt(0).toUpperCase()+n.slice(1)},n))})]}),pe(j,{path:"sceneConfig.postProcessing.toneMapping.resolution",label:"Resolution",value:t.resolution,min:64,max:4096,step:64,onChange:n=>o("toneMapping",{...t,resolution:n})}),pe(j,{path:"sceneConfig.postProcessing.toneMapping.whitePoint",label:"White point",value:t.whitePoint,min:0,max:16,step:.01,onChange:n=>o("toneMapping",{...t,whitePoint:n})}),pe(j,{path:"sceneConfig.postProcessing.toneMapping.middleGrey",label:"Middle grey",value:t.middleGrey,min:0,max:1,step:.01,onChange:n=>o("toneMapping",{...t,middleGrey:n})}),pe(j,{path:"sceneConfig.postProcessing.toneMapping.minLuminance",label:"Min luminance",value:t.minLuminance,min:0,max:1,step:.01,onChange:n=>o("toneMapping",{...t,minLuminance:n})}),pe(j,{path:"sceneConfig.postProcessing.toneMapping.averageLuminance",label:"Average luminance",value:t.averageLuminance,min:0,max:4,step:.01,onChange:n=>o("toneMapping",{...t,averageLuminance:n})}),pe(j,{path:"sceneConfig.postProcessing.toneMapping.adaptationRate",label:"Adaptation rate",value:t.adaptationRate,min:0,max:10,step:.01,onChange:n=>o("toneMapping",{...t,adaptationRate:n})}),pe(j,{path:"sceneConfig.postProcessing.toneMapping.exposure",label:"Exposure",value:t.exposure,min:0,max:3,step:.01,onChange:n=>o("toneMapping",{...t,exposure:n})})]})}function Pc({pp:e,set:o,open:i,toggle:r}){let{sepia:t}=e;return pe(ie,{title:"Sepia",tooltip:"Adds a warm vintage brown tint to the entire image.",open:i.sepia,onToggle:()=>r("sepia"),disabled:!t.enabled,trailing:pe(de,{checked:t.enabled,onChange:n=>o("sepia",{...t,enabled:n}),label:"Toggle sepia"}),children:pe(j,{path:"sceneConfig.postProcessing.sepia.intensity",label:"Intensity",value:t.intensity,min:0,max:1,step:.01,onChange:n=>o("sepia",{...t,intensity:n})})})}import{jsx as Y,jsxs as ci}from"react/jsx-runtime";function Bc({pp:e,set:o,open:i,toggle:r}){let{ssao:t}=e;return ci(ie,{title:"Ambient occlusion",tooltip:"Adds soft contact shadows in corners, creases, and tight spaces.",open:i.ssao,onToggle:()=>r("ssao"),disabled:!t.enabled,trailing:Y(de,{checked:t.enabled,onChange:n=>o("ssao",{...t,enabled:n}),label:"Toggle ssao"}),children:[Y(j,{path:"sceneConfig.postProcessing.ssao.samples",label:"Samples",value:t.samples,min:1,max:64,step:1,onChange:n=>o("ssao",{...t,samples:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.rings",label:"Rings",value:t.rings,min:1,max:12,step:1,onChange:n=>o("ssao",{...t,rings:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.intensity",label:"Intensity",value:t.intensity,min:0,max:20,step:.5,onChange:n=>o("ssao",{...t,intensity:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.radius",label:"Radius",value:t.radius,min:.01,max:1,step:.01,onChange:n=>o("ssao",{...t,radius:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.bias",label:"Bias",value:t.bias,min:0,max:.1,step:.001,onChange:n=>o("ssao",{...t,bias:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.luminanceInfluence",label:"Luminance influence",value:t.luminanceInfluence,min:0,max:1,step:.01,onChange:n=>o("ssao",{...t,luminanceInfluence:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.fade",label:"Fade",value:t.fade,min:0,max:.1,step:.001,onChange:n=>o("ssao",{...t,fade:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.minRadiusScale",label:"Min radius scale",value:t.minRadiusScale,min:0,max:1,step:.01,onChange:n=>o("ssao",{...t,minRadiusScale:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.worldDistanceThreshold",label:"World distance threshold",value:t.worldDistanceThreshold,min:0,max:100,step:.1,onChange:n=>o("ssao",{...t,worldDistanceThreshold:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.worldDistanceFalloff",label:"World distance falloff",value:t.worldDistanceFalloff,min:0,max:20,step:.1,onChange:n=>o("ssao",{...t,worldDistanceFalloff:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.worldProximityThreshold",label:"World proximity threshold",value:t.worldProximityThreshold,min:0,max:100,step:.1,onChange:n=>o("ssao",{...t,worldProximityThreshold:n})}),Y(j,{path:"sceneConfig.postProcessing.ssao.worldProximityFalloff",label:"World proximity falloff",value:t.worldProximityFalloff,min:0,max:20,step:.1,onChange:n=>o("ssao",{...t,worldProximityFalloff:n})})]})}function Tc({pp:e,set:o,open:i,toggle:r}){let{autofocus:t}=e;return ci(ie,{title:"Auto focus",tooltip:"Keeps the focus plane tracking a subject so the image stays sharp where you want it.",open:i.autofocus,onToggle:()=>r("autofocus"),disabled:!t.enabled,trailing:Y(de,{checked:t.enabled,onChange:n=>o("autofocus",{...t,enabled:n}),label:"Toggle autofocus"}),children:[Y(j,{path:"sceneConfig.postProcessing.autofocus.focusDistance",label:"Focus distance",value:t.focusDistance,min:0,max:50,step:.1,onChange:n=>o("autofocus",{...t,focusDistance:n})}),Y(j,{path:"sceneConfig.postProcessing.autofocus.focusRange",label:"Focus range",value:t.focusRange,min:.1,max:50,step:.1,onChange:n=>o("autofocus",{...t,focusRange:n})}),Y(j,{path:"sceneConfig.postProcessing.autofocus.focalLength",label:"Focal length",value:t.focalLength,min:0,max:1,step:.01,onChange:n=>o("autofocus",{...t,focalLength:n})}),Y(j,{path:"sceneConfig.postProcessing.autofocus.bokehScale",label:"Bokeh scale",value:t.bokehScale,min:0,max:20,step:.1,onChange:n=>o("autofocus",{...t,bokehScale:n})}),Y(xt,{path:"sceneConfig.postProcessing.autofocus.target",label:"Target",value:t.target,min:-100,max:100,step:.1,onChange:n=>o("autofocus",{...t,target:n})}),Y(he,{path:"sceneConfig.postProcessing.autofocus.mouse",label:"Mouse follow",checked:t.mouse,onChange:n=>o("autofocus",{...t,mouse:n})}),Y(he,{path:"sceneConfig.postProcessing.autofocus.manual",label:"Manual update",checked:t.manual,onChange:n=>o("autofocus",{...t,manual:n})}),Y(j,{path:"sceneConfig.postProcessing.autofocus.debug",label:"Debug",value:t.debug,min:0,max:1,step:.01,onChange:n=>o("autofocus",{...t,debug:n})}),Y(j,{path:"sceneConfig.postProcessing.autofocus.smoothTime",label:"Smooth time",value:t.smoothTime,min:0,max:2,step:.01,onChange:n=>o("autofocus",{...t,smoothTime:n})})]})}function Rc({pp:e,set:o,open:i,toggle:r}){let{godRays:t}=e;return ci(ie,{title:"God rays",tooltip:"Creates light shafts that streak outward from a bright sun or light source.",open:i.godRays,onToggle:()=>r("godRays"),disabled:!t.enabled,trailing:Y(de,{checked:t.enabled,onChange:n=>o("godRays",{...t,enabled:n}),label:"Toggle god rays"}),children:[Y(xt,{path:"sceneConfig.postProcessing.godRays.sunPosition",label:"Sun position",value:t.sunPosition,min:-100,max:100,step:.1,onChange:n=>o("godRays",{...t,sunPosition:n})}),Y(j,{path:"sceneConfig.postProcessing.godRays.samples",label:"Samples",value:t.samples,min:1,max:128,step:1,onChange:n=>o("godRays",{...t,samples:n})}),Y(j,{path:"sceneConfig.postProcessing.godRays.density",label:"Density",value:t.density,min:0,max:2,step:.01,onChange:n=>o("godRays",{...t,density:n})}),Y(j,{path:"sceneConfig.postProcessing.godRays.decay",label:"Decay",value:t.decay,min:0,max:1,step:.01,onChange:n=>o("godRays",{...t,decay:n})}),Y(j,{path:"sceneConfig.postProcessing.godRays.weight",label:"Weight",value:t.weight,min:0,max:2,step:.01,onChange:n=>o("godRays",{...t,weight:n})}),Y(j,{path:"sceneConfig.postProcessing.godRays.exposure",label:"Exposure",value:t.exposure,min:0,max:2,step:.01,onChange:n=>o("godRays",{...t,exposure:n})}),Y(j,{path:"sceneConfig.postProcessing.godRays.clampMax",label:"Clamp max",value:t.clampMax,min:0,max:2,step:.01,onChange:n=>o("godRays",{...t,clampMax:n})}),Y(he,{path:"sceneConfig.postProcessing.godRays.blur",label:"Blur",checked:t.blur,onChange:n=>o("godRays",{...t,blur:n})}),Y(pt,{path:"sceneConfig.postProcessing.godRays.kernelSize",label:"Kernel size",value:t.kernelSize,options:oi,onChange:n=>o("godRays",{...t,kernelSize:n})})]})}function Nc({pp:e,set:o,open:i,toggle:r}){let{lensflare:t}=e;return ci(ie,{title:"Lens flare",tooltip:"Adds camera flare artifacts and glow from a bright light source.",open:i.lensflare,onToggle:()=>r("lensflare"),disabled:!t.enabled,trailing:Y(de,{checked:t.enabled,onChange:n=>o("lensflare",{...t,enabled:n}),label:"Toggle lensflare"}),children:[Y(xt,{path:"sceneConfig.postProcessing.lensflare.lensPosition",label:"Lens position",value:t.lensPosition,min:-100,max:100,step:.1,onChange:n=>o("lensflare",{...t,lensPosition:n})}),Y(j,{path:"sceneConfig.postProcessing.lensflare.smoothTime",label:"Smooth time",value:t.smoothTime,min:0,max:1,step:.01,onChange:n=>o("lensflare",{...t,smoothTime:n})}),Y(j,{path:"sceneConfig.postProcessing.lensflare.glareSize",label:"Glare size",value:t.glareSize,min:0,max:1,step:.01,onChange:n=>o("lensflare",{...t,glareSize:n})}),Y(j,{path:"sceneConfig.postProcessing.lensflare.flareSize",label:"Flare size",value:t.flareSize,min:0,max:.1,step:.001,onChange:n=>o("lensflare",{...t,flareSize:n})}),Y(j,{path:"sceneConfig.postProcessing.lensflare.flareSpeed",label:"Flare speed",value:t.flareSpeed,min:0,max:.2,step:.001,onChange:n=>o("lensflare",{...t,flareSpeed:n})}),Y(j,{path:"sceneConfig.postProcessing.lensflare.flareShape",label:"Flare shape",value:t.flareShape,min:0,max:.2,step:.001,onChange:n=>o("lensflare",{...t,flareShape:n})}),Y(he,{path:"sceneConfig.postProcessing.lensflare.animated",label:"Animated",checked:t.animated,onChange:n=>o("lensflare",{...t,animated:n})}),Y(he,{path:"sceneConfig.postProcessing.lensflare.anamorphic",label:"Anamorphic",checked:t.anamorphic,onChange:n=>o("lensflare",{...t,anamorphic:n})}),Y(ht,{path:"sceneConfig.postProcessing.lensflare.colorGain",label:"Color gain",value:t.colorGain,onChange:n=>o("lensflare",{...t,colorGain:n})}),Y(j,{path:"sceneConfig.postProcessing.lensflare.haloScale",label:"Halo scale",value:t.haloScale,min:0,max:2,step:.01,onChange:n=>o("lensflare",{...t,haloScale:n})}),Y(he,{path:"sceneConfig.postProcessing.lensflare.secondaryGhosts",label:"Secondary ghosts",checked:t.secondaryGhosts,onChange:n=>o("lensflare",{...t,secondaryGhosts:n})}),Y(he,{path:"sceneConfig.postProcessing.lensflare.aditionalStreaks",label:"Additional streaks",checked:t.aditionalStreaks,onChange:n=>o("lensflare",{...t,aditionalStreaks:n})}),Y(j,{path:"sceneConfig.postProcessing.lensflare.ghostScale",label:"Ghost scale",value:t.ghostScale,min:0,max:1,step:.01,onChange:n=>o("lensflare",{...t,ghostScale:n})}),Y(j,{path:"sceneConfig.postProcessing.lensflare.opacity",label:"Opacity",value:t.opacity,min:0,max:1,step:.01,onChange:n=>o("lensflare",{...t,opacity:n})}),Y(he,{path:"sceneConfig.postProcessing.lensflare.starBurst",label:"Star burst",checked:t.starBurst,onChange:n=>o("lensflare",{...t,starBurst:n})})]})}function Ac({pp:e,set:o,open:i,toggle:r}){let{depthOfField:t}=e;return ci(ie,{title:"Depth of field",tooltip:"Blurs areas that sit away from the focal plane for a camera-like look.",open:i.depthOfField,onToggle:()=>r("depthOfField"),disabled:!t.enabled,trailing:Y(de,{checked:t.enabled,onChange:n=>o("depthOfField",{...t,enabled:n}),label:"Toggle depth of field"}),children:[Y(j,{path:"sceneConfig.postProcessing.depthOfField.focusDistance",label:"Focus distance",value:t.focusDistance,min:0,max:50,step:.1,onChange:n=>o("depthOfField",{...t,focusDistance:n})}),Y(j,{path:"sceneConfig.postProcessing.depthOfField.focusRange",label:"Focus range",value:t.focusRange,min:.1,max:50,step:.1,onChange:n=>o("depthOfField",{...t,focusRange:n})}),Y(j,{path:"sceneConfig.postProcessing.depthOfField.focalLength",label:"Focal length",value:t.focalLength,min:0,max:1,step:.01,onChange:n=>o("depthOfField",{...t,focalLength:n})}),Y(j,{path:"sceneConfig.postProcessing.depthOfField.bokehScale",label:"Bokeh scale",value:t.bokehScale,min:0,max:20,step:.1,onChange:n=>o("depthOfField",{...t,bokehScale:n})})]})}import{jsx as ae,jsxs as In}from"react/jsx-runtime";function Oc({pp:e,set:o,open:i,toggle:r}){let{dotScreen:t}=e;return In(ie,{title:"Dot screen",tooltip:"Overlays a halftone dot pattern for a printed or retro look.",open:i.dotScreen,onToggle:()=>r("dotScreen"),disabled:!t.enabled,trailing:ae(de,{checked:t.enabled,onChange:n=>o("dotScreen",{...t,enabled:n}),label:"Toggle dot screen"}),children:[ae(j,{path:"sceneConfig.postProcessing.dotScreen.angle",label:"Angle",value:t.angle,min:0,max:Math.PI*2,step:.01,formatValue:n=>`${n.toFixed(2)} rad`,onChange:n=>o("dotScreen",{...t,angle:n})}),ae(j,{path:"sceneConfig.postProcessing.dotScreen.scale",label:"Scale",value:t.scale,min:.1,max:10,step:.05,onChange:n=>o("dotScreen",{...t,scale:n})})]})}function Ec({pp:e,set:o,open:i,toggle:r}){let{glitch:t}=e;return In(ie,{title:"Glitch",tooltip:"Introduces digital distortion, tearing, and scan noise.",open:i.glitch,onToggle:()=>r("glitch"),disabled:!t.enabled,trailing:ae(de,{checked:t.enabled,onChange:n=>o("glitch",{...t,enabled:n}),label:"Toggle glitch"}),children:[ae(pt,{path:"sceneConfig.postProcessing.glitch.mode",label:"Mode",value:t.mode,options:Ul,onChange:n=>o("glitch",{...t,mode:n})}),ae(Jo,{path:"sceneConfig.postProcessing.glitch.delay",label:"Delay",value:t.delay,min:0,max:10,step:.01,onChange:n=>o("glitch",{...t,delay:n})}),ae(Jo,{path:"sceneConfig.postProcessing.glitch.duration",label:"Duration",value:t.duration,min:0,max:5,step:.01,onChange:n=>o("glitch",{...t,duration:n})}),ae(Jo,{path:"sceneConfig.postProcessing.glitch.strength",label:"Strength",value:t.strength,min:0,max:2,step:.01,onChange:n=>o("glitch",{...t,strength:n})}),ae(Jo,{path:"sceneConfig.postProcessing.glitch.chromaticAberrationOffset",label:"Chromatic aberration offset",value:t.chromaticAberrationOffset,min:0,max:.02,step:1e-4,onChange:n=>o("glitch",{...t,chromaticAberrationOffset:n})}),ae(j,{path:"sceneConfig.postProcessing.glitch.columns",label:"Columns",value:t.columns,min:0,max:.5,step:.001,onChange:n=>o("glitch",{...t,columns:n})}),ae(j,{path:"sceneConfig.postProcessing.glitch.ratio",label:"Ratio",value:t.ratio,min:0,max:1,step:.01,onChange:n=>o("glitch",{...t,ratio:n})})]})}function jc({pp:e,set:o,open:i,toggle:r}){let{grid:t}=e;return In(ie,{title:"Grid",tooltip:"Adds a visual grid overlay that feels retro or debug-like.",open:i.grid,onToggle:()=>r("grid"),disabled:!t.enabled,trailing:ae(de,{checked:t.enabled,onChange:n=>o("grid",{...t,enabled:n}),label:"Toggle grid"}),children:[ae(j,{path:"sceneConfig.postProcessing.grid.scale",label:"Scale",value:t.scale,min:.1,max:10,step:.05,onChange:n=>o("grid",{...t,scale:n})}),ae(j,{path:"sceneConfig.postProcessing.grid.lineWidth",label:"Line width",value:t.lineWidth,min:0,max:1,step:.01,onChange:n=>o("grid",{...t,lineWidth:n})})]})}function Ic({pp:e,set:o,open:i,toggle:r}){let{chromaticAberration:t}=e;return In(ie,{title:"Chromatic aberration",tooltip:"Separates color channels slightly to mimic lens fringing.",open:i.chromaticAberration,onToggle:()=>r("chromaticAberration"),disabled:!t.enabled,trailing:ae(de,{checked:t.enabled,onChange:n=>o("chromaticAberration",{...t,enabled:n}),label:"Toggle chromatic aberration"}),children:[ae(j,{path:"sceneConfig.postProcessing.chromaticAberration.offsetX",label:"Offset X",value:t.offsetX,min:0,max:.02,step:1e-4,onChange:n=>o("chromaticAberration",{...t,offsetX:n})}),ae(j,{path:"sceneConfig.postProcessing.chromaticAberration.offsetY",label:"Offset Y",value:t.offsetY,min:0,max:.02,step:1e-4,onChange:n=>o("chromaticAberration",{...t,offsetY:n})}),ae(he,{path:"sceneConfig.postProcessing.chromaticAberration.radialModulation",label:"Radial modulation",checked:t.radialModulation,onChange:n=>o("chromaticAberration",{...t,radialModulation:n})}),ae(j,{path:"sceneConfig.postProcessing.chromaticAberration.modulationOffset",label:"Modulation offset",value:t.modulationOffset,min:0,max:1,step:.01,onChange:n=>o("chromaticAberration",{...t,modulationOffset:n})})]})}function zc({pp:e,set:o,open:i,toggle:r}){let{noise:t}=e;return In(ie,{title:"Noise",tooltip:"Adds film grain or static noise to the rendered image.",open:i.noise,onToggle:()=>r("noise"),disabled:!t.enabled,trailing:ae(de,{checked:t.enabled,onChange:n=>o("noise",{...t,enabled:n}),label:"Toggle noise"}),children:[ae(j,{path:"sceneConfig.postProcessing.noise.opacity",label:"Amount",value:t.opacity,min:0,max:1,step:.01,onChange:n=>o("noise",{...t,opacity:n})}),ae(he,{path:"sceneConfig.postProcessing.noise.premultiply",label:"Premultiply",checked:t.premultiply,onChange:n=>o("noise",{...t,premultiply:n})})]})}function Dc({pp:e,set:o,open:i,toggle:r}){let{scanline:t}=e;return ae(ie,{title:"Scan lines",tooltip:"Draws horizontal CRT-style scan lines over the frame.",open:i.scanline,onToggle:()=>r("scanline"),disabled:!t.enabled,trailing:ae(de,{checked:t.enabled,onChange:n=>o("scanline",{...t,enabled:n}),label:"Toggle scanline"}),children:ae(j,{path:"sceneConfig.postProcessing.scanline.density",label:"Density",value:t.density,min:0,max:10,step:.25,onChange:n=>o("scanline",{...t,density:n})})})}function Lc({pp:e,set:o,open:i,toggle:r}){let{pixelation:t}=e;return ae(ie,{title:"Pixelation",tooltip:"Reduces detail into larger pixels for a blocky stylized effect.",open:i.pixelation,onToggle:()=>r("pixelation"),disabled:!t.enabled,trailing:ae(de,{checked:t.enabled,onChange:n=>o("pixelation",{...t,enabled:n}),label:"Toggle pixelation"}),children:ae(j,{path:"sceneConfig.postProcessing.pixelation.granularity",label:"Granularity",value:t.granularity,min:0,max:20,step:1,onChange:n=>o("pixelation",{...t,granularity:n})})})}function Fc({pp:e,set:o,open:i,toggle:r}){let{ramp:t}=e;return In(ie,{title:"Color ramp",tooltip:"Adds a screen-space color gradient, or masks effects earlier in the stack.",open:i.ramp,onToggle:()=>r("ramp"),disabled:!t.enabled,trailing:ae(de,{checked:t.enabled,onChange:n=>o("ramp",{...t,enabled:n}),label:"Toggle ramp"}),children:[ae(pt,{path:"sceneConfig.postProcessing.ramp.rampType",label:"Ramp type",value:t.rampType,options:Vl,onChange:n=>o("ramp",{...t,rampType:n})}),ae(Jo,{path:"sceneConfig.postProcessing.ramp.rampStart",label:"Ramp start",value:t.rampStart,min:0,max:1,step:.01,onChange:n=>o("ramp",{...t,rampStart:n})}),ae(Jo,{path:"sceneConfig.postProcessing.ramp.rampEnd",label:"Ramp end",value:t.rampEnd,min:0,max:1,step:.01,onChange:n=>o("ramp",{...t,rampEnd:n})}),ae(ht,{path:"sceneConfig.postProcessing.ramp.startColor",label:"Start color",value:t.startColor,onChange:n=>o("ramp",{...t,startColor:n})}),ae(ht,{path:"sceneConfig.postProcessing.ramp.endColor",label:"End color",value:t.endColor,onChange:n=>o("ramp",{...t,endColor:n})}),!t.rampMask&&ae(j,{path:"sceneConfig.postProcessing.ramp.opacity",label:"Gradient opacity",value:t.opacity??.5,min:0,max:1,step:.01,onChange:n=>o("ramp",{...t,opacity:n})}),ae(j,{path:"sceneConfig.postProcessing.ramp.rampBias",label:"Bias",value:t.rampBias,min:0,max:1,step:.01,onChange:n=>o("ramp",{...t,rampBias:n})}),ae(j,{path:"sceneConfig.postProcessing.ramp.rampGain",label:"Gain",value:t.rampGain,min:0,max:1,step:.01,onChange:n=>o("ramp",{...t,rampGain:n})}),ae(he,{path:"sceneConfig.postProcessing.ramp.rampMask",label:"Mask earlier effects",checked:t.rampMask,onChange:n=>o("ramp",{...t,rampMask:n})}),ae(he,{path:"sceneConfig.postProcessing.ramp.rampInvert",label:"Invert",checked:t.rampInvert,onChange:n=>o("ramp",{...t,rampInvert:n})})]})}import{jsx as Ae,jsxs as Vc}from"react/jsx-runtime";function Hc({pp:e,set:o,open:i,toggle:r}){let{outline:t}=e;return Vc(ie,{title:"Outline",tooltip:"Draws a visible edge around the selected object binding.",open:i.outline,onToggle:()=>r("outline"),disabled:!t.enabled,trailing:Ae(de,{checked:t.enabled,onChange:n=>o("outline",{...t,enabled:n}),label:"Toggle outline"}),children:[Ae("div",{className:"se-placeholder",children:"Outlines the currently selected object binding in the model editor."}),Ae(j,{path:"sceneConfig.postProcessing.outline.selectionLayer",label:"Selection layer",value:t.selectionLayer,min:0,max:20,step:1,onChange:n=>o("outline",{...t,selectionLayer:n})}),Ae(j,{path:"sceneConfig.postProcessing.outline.edgeStrength",label:"Edge strength",value:t.edgeStrength,min:0,max:10,step:.1,onChange:n=>o("outline",{...t,edgeStrength:n})}),Ae(j,{path:"sceneConfig.postProcessing.outline.pulseSpeed",label:"Pulse speed",value:t.pulseSpeed,min:0,max:10,step:.1,onChange:n=>o("outline",{...t,pulseSpeed:n})}),Ae(ht,{path:"sceneConfig.postProcessing.outline.visibleEdgeColor",label:"Visible edge color",value:t.visibleEdgeColor,onChange:n=>o("outline",{...t,visibleEdgeColor:n})}),Ae(ht,{path:"sceneConfig.postProcessing.outline.hiddenEdgeColor",label:"Hidden edge color",value:t.hiddenEdgeColor,onChange:n=>o("outline",{...t,hiddenEdgeColor:n})}),Ae(pt,{path:"sceneConfig.postProcessing.outline.kernelSize",label:"Kernel size",value:t.kernelSize,options:oi,onChange:n=>o("outline",{...t,kernelSize:n})}),Ae(he,{path:"sceneConfig.postProcessing.outline.blur",label:"Blur",checked:t.blur,onChange:n=>o("outline",{...t,blur:n})}),Ae(he,{path:"sceneConfig.postProcessing.outline.xRay",label:"X-Ray",checked:t.xRay,onChange:n=>o("outline",{...t,xRay:n})})]})}function $c({pp:e,set:o,open:i,toggle:r}){let{selectiveBloom:t}=e;return Vc(ie,{title:"Selective bloom",tooltip:"Applies bloom only to objects assigned to the selected layer.",open:i.selectiveBloom,onToggle:()=>r("selectiveBloom"),disabled:!t.enabled,trailing:Ae(de,{checked:t.enabled,onChange:n=>o("selectiveBloom",{...t,enabled:n}),label:"Toggle selective bloom"}),children:[Ae("div",{className:"se-placeholder",children:"Applies bloom to the currently selected object binding."}),Ae(j,{path:"sceneConfig.postProcessing.selectiveBloom.selectionLayer",label:"Selection layer",value:t.selectionLayer,min:0,max:20,step:1,onChange:n=>o("selectiveBloom",{...t,selectionLayer:n})}),Ae(j,{path:"sceneConfig.postProcessing.selectiveBloom.intensity",label:"Intensity",value:t.intensity,min:0,max:5,step:.05,onChange:n=>o("selectiveBloom",{...t,intensity:n})}),Ae(j,{path:"sceneConfig.postProcessing.selectiveBloom.luminanceThreshold",label:"Threshold",value:t.luminanceThreshold,min:0,max:1,step:.01,onChange:n=>o("selectiveBloom",{...t,luminanceThreshold:n})}),Ae(j,{path:"sceneConfig.postProcessing.selectiveBloom.luminanceSmoothing",label:"Smoothing",value:t.luminanceSmoothing,min:0,max:1,step:.01,onChange:n=>o("selectiveBloom",{...t,luminanceSmoothing:n})}),Ae(pt,{path:"sceneConfig.postProcessing.selectiveBloom.kernelSize",label:"Kernel size",value:t.kernelSize,options:oi,onChange:n=>o("selectiveBloom",{...t,kernelSize:n})}),Ae(he,{path:"sceneConfig.postProcessing.selectiveBloom.mipmapBlur",label:"Mipmap blur",checked:t.mipmapBlur,onChange:n=>o("selectiveBloom",{...t,mipmapBlur:n})}),Ae(he,{path:"sceneConfig.postProcessing.selectiveBloom.inverted",label:"Inverted",checked:t.inverted,onChange:n=>o("selectiveBloom",{...t,inverted:n})}),Ae(he,{path:"sceneConfig.postProcessing.selectiveBloom.ignoreBackground",label:"Ignore background",checked:t.ignoreBackground,onChange:n=>o("selectiveBloom",{...t,ignoreBackground:n})})]})}function Uc({pp:e,set:o,open:i,toggle:r}){let{smaa:t}=e;return Ae(ie,{title:"Anti-aliasing",tooltip:"Reduces jagged edges with subpixel anti-aliasing.",open:i.smaa,onToggle:()=>r("smaa"),trailing:Ae(de,{checked:t.enabled,onChange:n=>o("smaa",{...t,enabled:n}),label:"Toggle smaa"}),children:Ae("div",{className:"se-placeholder",children:"Subpixel Morphological Anti-Aliasing smooths jagged edges in post-process."})})}import{jsx as Jt,jsxs as pi}from"react/jsx-runtime";var _c=[{key:"toneMapping",label:"Tone mapping",group:"Color",Section:Mc},{key:"brightnessContrast",label:"Brightness and contrast",group:"Color",Section:wc},{key:"hueSaturation",label:"Hue and saturation",group:"Color",Section:Sc},{key:"colorAverage",label:"Color average",group:"Color",Section:yc},{key:"sepia",label:"Sepia",group:"Color",Section:Pc},{key:"vignette",label:"Vignette",group:"Color",Section:kc},{key:"bloom",label:"Bloom",group:"Lighting",Section:Cc},{key:"ssao",label:"Ambient occlusion",hint:"SSAO",group:"Lighting",feature:"postLighting",Section:Bc},{key:"depthOfField",label:"Depth of field",group:"Lighting",feature:"postLighting",Section:Ac},{key:"autofocus",label:"Auto focus",group:"Lighting",feature:"postLighting",Section:Tc},{key:"godRays",label:"God rays",group:"Lighting",feature:"postLighting",Section:Rc},{key:"lensflare",label:"Lens flare",group:"Lighting",feature:"postLighting",Section:Nc},{key:"outline",label:"Outline",group:"Selection",feature:"postSelection",Section:Hc},{key:"selectiveBloom",label:"Selective bloom",group:"Selection",feature:"postSelection",Section:$c},{key:"smaa",label:"Anti-aliasing",hint:"SMAA",group:"Selection",feature:"postSelection",Section:Uc},{key:"chromaticAberration",label:"Chromatic aberration",group:"Stylize",feature:"postSelection",Section:Ic},{key:"dotScreen",label:"Dot screen",group:"Stylize",feature:"postSelection",Section:Oc},{key:"glitch",label:"Glitch",group:"Stylize",feature:"postSelection",Section:Ec},{key:"grid",label:"Grid",group:"Stylize",feature:"postSelection",Section:jc},{key:"noise",label:"Noise",group:"Stylize",feature:"postSelection",Section:zc},{key:"pixelation",label:"Pixelation",group:"Stylize",feature:"postSelection",Section:Lc},{key:"ramp",label:"Color ramp",group:"Stylize",feature:"postSelection",Section:Fc},{key:"scanline",label:"Scan lines",group:"Stylize",feature:"postSelection",Section:Dc}],Ym=["Color","Lighting","Selection","Stylize"],Jm={postLighting:"starter",postSelection:"growth"};function ja({config:e,onChange:o}){let[i,r]=gr({}),[t,n]=gr(()=>new Set),[c,s]=gr(!1),[p,f]=gr(null),u=Gm(null);Bn([u],()=>s(!1),c),Km(()=>{if(!c)return;let b=N=>{N.key==="Escape"&&s(!1)};return window.addEventListener("keydown",b),()=>window.removeEventListener("keydown",b)},[c]);let h=b=>r(N=>({...N,[b]:!N[b]})),{tier:m}=lt(),C=e.postProcessing,B=(b,N)=>o({...e,postProcessing:{...C,[b]:N}}),w=b=>!b.feature||st(m,b.feature),P=_c.filter(b=>w(b)&&(C[b.key]?.enabled===!0||t.has(b.key))),v=_c.filter(b=>!P.includes(b)),d={pp:C,set:B,open:i,toggle:h},x=b=>{if(s(!1),!w(b)){f(b);return}f(null),n(N=>new Set(N).add(b.key)),r(N=>({...N,[b.key]:!0})),B(b.key,{...C[b.key],enabled:!0})};return pi("div",{className:"se-generalContent",children:[pi("div",{className:"se-listHeader",ref:u,children:[Jt("span",{children:"Effects"}),pi("button",{type:"button",className:"bb-button bb-button--ghost bb-button--small","aria-expanded":c,disabled:!v.length,onClick:()=>s(b=>!b),children:[Jt(Wm,{size:13,"aria-hidden":"true"}),"Add effect"]}),c?Jt("div",{className:"se-addMenu",role:"menu","aria-label":"Add effect",children:Ym.map(b=>{let N=v.filter(A=>A.group===b);return N.length?pi("div",{role:"group","aria-label":b,children:[Jt("h6",{children:b}),N.map(A=>pi("button",{type:"button",role:"menuitem",onClick:()=>x(A),children:[Jt("span",{children:A.label}),A.hint?Jt("small",{children:A.hint}):null,w(A)?null:Jt(qm,{size:12,"aria-label":"Needs an upgrade"})]},A.key))]},b):null})}):null]}),p?.feature?Jt(Ye,{requiredTier:Jm[p.feature],feature:p.label}):null,P.length?null:Jt("p",{className:"se-listEmpty",children:"Add an effect to shape the final image, starting with tone mapping or bloom."}),P.map(({key:b,Section:N})=>Jt(N,{...d},b))]})}import{useState as Kc,useSyncExternalStore as Xm}from"react";import{Eye as Zm,EyeOff as Qm,Plus as ef,Trash2 as tf}from"lucide-react";import{Fragment as af,jsx as xe,jsxs as go}from"react/jsx-runtime";var of=["512","1024","2048","4096"],Gc={none:"None",directional:"Directional",point:"Point",spot:"Spot",hemisphere:"Hemisphere"};function nf({index:e,light:o,selected:i,onSelect:r,onToggleVisible:t}){return go("div",{className:`se-lightRow ${i?"se-lightRow--active":""}`,onClick:r,children:[go("span",{className:"se-lightRowLabel",children:[e+1,": ",Gc[o.type]]}),xe("button",{type:"button",className:"se-iconButton","aria-label":o.visible?"Hide light":"Show light",onClick:n=>{n.stopPropagation(),t()},children:o.visible?xe(Zm,{size:14}):xe(Qm,{size:14})})]})}function rf(){return{id:crypto.randomUUID(),type:"directional",color:"#ffffff",intensity:1,position:[5,10,5],attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0}}function Ia({config:e,onChange:o}){let[i,r]=Kc({lights:!0,shadows:!1,groundShadows:!1,environment:!1,envShadow:!1}),t=Xm(fd,hd),[n,c]=Kc(e.lighting.lights[0]?.id??null),s=t??n,p=T=>{c(T),md(T)},f=T=>r(z=>({...z,[T]:!z[T]})),{tier:u}=lt(),{lighting:h,shadows:m,groundShadows:C,environment:B}=e,w=T=>o({...e,lighting:T}),P=T=>o({...e,shadows:T}),v=T=>o({...e,groundShadows:T}),d=T=>o({...e,environment:T}),x=(T,z)=>{w({...h,lights:h.lights.map(y=>y.id===T?{...y,...z}:y)})},b=h.lights.find(T=>T.id===s)??null,N=()=>{let T=rf();w({...h,lights:[...h.lights,T]}),p(T.id)},A=()=>{if(!b)return;let T=h.lights.filter(z=>z.id!==b.id);w({...h,lights:T}),p(T[0]?.id??null)},K=Tt(u,"lights",h.lights.length);return go("div",{className:"se-generalContent",children:[go(ie,{title:"Lights",open:i.lights,onToggle:()=>f("lights"),trailing:go("span",{className:"se-listHeaderActions",children:[b&&h.lights.length>1?xe("button",{type:"button",className:"se-iconButton",onClick:A,title:"Remove selected light","aria-label":"Remove selected light",children:xe(tf,{size:13})}):null,xe("button",{type:"button",className:"se-iconButton",onClick:N,disabled:!K,title:"Add light","aria-label":"Add light",children:xe(ef,{size:14})})]}),children:[xe("div",{className:"se-lightList",children:h.lights.map((T,z)=>xe(nf,{index:z,light:T,selected:T.id===s,onSelect:()=>p(T.id),onToggleVisible:()=>x(T.id,{visible:!T.visible})},T.id))}),K?null:xe(Ye,{requiredTier:Yo("lights",h.lights.length),feature:"More lights"}),b?go("div",{className:"se-lightProps",children:[go("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:b.type,onChange:T=>x(b.id,{type:T.target.value}),children:Fl.map(T=>xe("option",{value:T,children:Gc[T]},T))})]}),xe(ht,{path:"sceneConfig.lighting.lights[\u2026].color",label:"Color",value:b.color,onChange:T=>x(b.id,{color:T})}),xe(j,{path:"sceneConfig.lighting.lights[\u2026].intensity",label:"Intensity",value:b.intensity,min:0,max:10,step:.1,onChange:T=>x(b.id,{intensity:T})}),b.type!=="hemisphere"&&b.type!=="none"&&xe(xt,{path:"sceneConfig.lighting.lights[\u2026].position",label:"Position",value:b.position,min:-100,max:100,step:.05,onChange:T=>x(b.id,{position:T})}),(b.type==="spot"||b.type==="directional")&&xe(xt,{path:"sceneConfig.lighting.lights[\u2026].target",label:"Target",value:b.target??[0,0,0],min:-100,max:100,step:.05,onChange:T=>x(b.id,{target:T})}),b.type==="spot"&&go(af,{children:[xe(j,{path:"sceneConfig.lighting.lights[\u2026].angle",label:"Angle",value:b.angle??Math.PI/6,min:0,max:Math.PI/2,step:.01,formatValue:T=>`${Math.round(T*180/Math.PI)}\xB0`,onChange:T=>x(b.id,{angle:T})}),xe(j,{path:"sceneConfig.lighting.lights[\u2026].penumbra",label:"Penumbra",value:b.penumbra??.2,min:0,max:1,step:.01,onChange:T=>x(b.id,{penumbra:T})}),xe(j,{path:"sceneConfig.lighting.lights[\u2026].distance",label:"Distance",value:b.distance??0,min:0,max:100,step:.5,onChange:T=>x(b.id,{distance:T})}),xe(j,{path:"sceneConfig.lighting.lights[\u2026].decay",label:"Decay",value:b.decay??2,min:0,max:4,step:.1,onChange:T=>x(b.id,{decay:T})})]}),xe(he,{path:"sceneConfig.lighting.lights[\u2026].attachedToCamera",label:"Attached to camera",checked:b.attachedToCamera,onChange:T=>x(b.id,{attachedToCamera:T})}),xe(he,{path:"sceneConfig.lighting.lights[\u2026].castShadow",label:"Cast shadows",checked:b.castShadow,onChange:T=>x(b.id,{castShadow:T})}),xe(j,{path:"sceneConfig.lighting.lights[\u2026].shadowBias",label:"Shadow bias",value:b.shadowBias,min:-.01,max:.01,step:1e-4,onChange:T=>x(b.id,{shadowBias:T}),disabled:!b.castShadow||!m.enabled}),!b.castShadow||!m.enabled?xe("span",{className:"bb-note",children:m.enabled?"Turn on Cast shadows for this light to use Shadow bias.":"Turn on Shadows below to use Shadow bias."}):null]}):null]}),go(ie,{title:"Shadows",open:i.shadows,onToggle:()=>f("shadows"),disabled:!m.enabled,trailing:xe(de,{checked:m.enabled,onChange:T=>P({...m,enabled:T}),label:"Toggle shadows"}),children:[xe(pt,{label:"Map size",value:String(m.mapSize),options:of,onChange:T=>P({...m,mapSize:Number(T)})}),xe(j,{path:"sceneConfig.shadows.bias",label:"Bias",value:m.bias,min:-.01,max:.01,step:1e-4,onChange:T=>P({...m,bias:T})}),xe(j,{path:"sceneConfig.shadows.normalBias",label:"Normal bias",value:m.normalBias,min:0,max:.2,step:.01,onChange:T=>P({...m,normalBias:T})}),xe(j,{path:"sceneConfig.shadows.radius",label:"Radius (softness)",value:m.radius,min:0,max:20,step:.5,onChange:T=>P({...m,radius:T})})]})]})}import{lazy as sf,Suspense as lf}from"react";import{jsx as za}from"react/jsx-runtime";function Oo(e){let o=sf(e);return function(r){return za(lf,{fallback:za("p",{className:"bb-panelEmpty",children:"Loading\u2026"}),children:za(o,{...r})})}}import{jsx as en,jsxs as uf}from"react/jsx-runtime";var df=Oo(()=>import("./RulesTab-YVBZGJZX.mjs")),qc=[{id:"model",label:"Model"},{id:"camera",label:"Camera"},{id:"world",label:"World"},{id:"lighting",label:"Lights"},{id:"postProcessing",label:"Effects"},{id:"rules",label:"Rules"}],cf=[],pf={};function Da({diagnostics:e,onDiagnosticsOpenChange:o,config:i,onChange:r,activeSubTab:t,materialVariantGroups:n=cf,onImageFile:c,objectBindings:s=pf}){let{tier:p}=lt();return uf("div",{className:"se-tabContent",children:[t==="model"&&en(hc,{diagnostics:e,onDiagnosticsOpenChange:o,config:i,onChange:r,materialVariantGroups:n}),t==="camera"&&en(xc,{config:i,onChange:r}),t==="world"&&en(vc,{config:i,onChange:r,onImageFile:c}),t==="lighting"&&en(Ia,{config:i,onChange:r}),t==="postProcessing"&&en(ja,{config:i,onChange:r}),t==="rules"&&(st(p,"rules")?en(df,{config:i,onChange:r,objectBindings:s}):en(Ye,{requiredTier:"growth",feature:"Rules"}))]})}import{ChevronRight as Wc,Info as Yc}from"lucide-react";import{jsx as Xt,jsxs as zn}from"react/jsx-runtime";function Jc({title:e,trailing:o,children:i,disabled:r,open:t,onToggle:n,tooltip:c}){return zn("div",{className:"bb-materialPanel","data-ri-section":e,children:[zn("div",{className:"bb-materialPanelHeaderRow",children:[zn("button",{type:"button",className:"bb-materialPanelHeader",onClick:n,"aria-expanded":t,title:c,children:[Xt(Wc,{size:13,className:`bb-materialPanelChevron ${t?"bb-materialPanelChevron--open":""}`}),Xt("span",{className:"bb-materialPanelTitle",children:e}),c?Xt(Yc,{size:11,className:"bb-materialPanelHelp","aria-hidden":"true"}):null]}),o?Xt("span",{className:"bb-materialPanelTrailing",children:o}):null]}),t?Xt("div",{className:`bb-materialPanelBody ${r?"bb-materialPanelBody--disabled":""}`,children:i}):null]})}function Je({title:e,open:o,onToggle:i,trailing:r,children:t,tooltip:n}){return zn("div",{className:"bb-section","data-ri-section":e,children:[zn("div",{className:"bb-sectionHeaderRow",children:[zn("button",{type:"button",className:"bb-sectionHeaderButton",onClick:i,"aria-expanded":o,title:n,children:[Xt(Wc,{size:13,className:`bb-sectionChevron ${o?"bb-sectionChevron--open":""}`}),Xt("h2",{className:"bb-sectionTitle",children:e}),n?Xt(Yc,{size:11,className:"bb-sectionHelp","aria-hidden":"true"}):null]}),r?Xt("span",{className:"bb-sectionHeaderTrailing",children:r}):null]}),o?Xt("div",{className:"bb-sectionBody",children:t}):null]})}import{Copy as bf,Plus as gf,Scan as mf,Trash2 as ff}from"lucide-react";import{Fragment as hf,jsx as Oe,jsxs as Zt}from"react/jsx-runtime";function La(e){let o=e.assets.find(t=>t.url===e.activeUrl),i=o?.placement??{},r=e.assets.length<2?"Use Remove model to clear the last model":e.deleteIsPermanent?"Delete model":"Delete model (undoable)";return Zt("div",{className:"ri-assets",children:[Zt(jd,{title:"Models",children:[Oe("button",{type:"button",className:"se-iconButton",title:"Frame all models","aria-label":"Frame all models",onClick:e.onFrameAll,children:Oe(mf,{size:13})}),Oe("button",{type:"button",className:"se-iconButton",title:"Add model","aria-label":"Add model",disabled:e.busy||!!e.addRequiresTier,onClick:e.onAdd,children:Oe(gf,{size:14})})]}),e.addRequiresTier?Oe(Ye,{requiredTier:e.addRequiresTier,feature:"More models in a project"}):null,Oe("ul",{className:"ri-assets-list","aria-label":"Models in this scene",children:e.assets.map(t=>Oe("li",{children:Zt("button",{type:"button",className:t.url===e.activeUrl?"ri-assets-item is-active":"ri-assets-item","aria-pressed":t.url===e.activeUrl,onClick:()=>e.onSelect(t.url),children:[Oe("span",{className:"ri-assets-itemName",children:t.displayName??t.placement.label??t.name}),Oe("small",{children:t.placement.visible===!1?"Hidden":t.ready?null:"Loading"})]})},t.id))}),o&&Zt(hf,{children:[Zt(Sa,{title:"Placement",children:[Oe(Tn,{label:"Name",children:Oe("input",{className:"se-textInput","aria-label":"Model name",value:i.label??o.name,maxLength:512,onChange:t=>e.onChange(o.id,{label:t.target.value})})}),Oe(he,{label:"Visible",checked:i.visible!==!1,onChange:t=>e.onChange(o.id,{visible:t})}),Oe(xt,{min:-1e6,max:1e6,label:"Position",value:i.position??[0,0,0],step:.1,onChange:t=>e.onChange(o.id,{position:t})}),Oe(xt,{min:-1e6,max:1e6,label:"Rotation",value:(i.rotation??[0,0,0]).map(t=>t*180/Math.PI),step:1,onChange:t=>e.onChange(o.id,{rotation:t.map(n=>n*Math.PI/180)})}),Oe(xt,{min:-1e6,max:1e6,label:"Scale",value:i.scale??[1,1,1],step:.1,onChange:t=>{t.every(n=>n!==0)&&e.onChange(o.id,{scale:t})}})]}),Zt(Sa,{title:"Align",children:[Oe(Tn,{label:"Grid spacing",children:Oe("input",{className:"se-numberInput","aria-label":"Grid spacing",type:"number",min:.001,step:.1,value:e.composition.gridSize,onChange:t=>{let n=Number(t.target.value);Number.isFinite(n)&&n>0&&e.onGridSize(n)}})}),Zt(co,{children:[Oe("button",{type:"button",className:"bb-button",onClick:()=>e.onSnap(o.id),children:"Snap to grid"}),Oe("button",{type:"button",className:"bb-button",disabled:!o.ready,onClick:()=>e.onGround(o.url),children:"Place on ground"})]})]}),Zt(co,{children:[Zt("button",{type:"button",className:"bb-button",disabled:e.busy||!o.ready,onClick:()=>e.onDuplicate(o.url),children:[Oe(bf,{size:13,"aria-hidden":"true"}),"Duplicate"]}),Zt("button",{type:"button",className:"bb-button",disabled:e.busy||e.assets.length<2,title:r,onClick:()=>e.onDelete(o.url),children:[Oe(ff,{size:13,"aria-hidden":"true"}),"Delete"]})]}),Oe("p",{className:"rui-footnote",title:"Instance ID",children:Oe("code",{children:o.id})})]})]})}import{useEffect as xf,useId as vf,useRef as Xc,useState as yf}from"react";import{ChevronDown as wf,Download as Sf,FileArchive as kf,FileCode2 as Cf,FileJson as Zc,Upload as Mf}from"lucide-react";import{jsx as Nt,jsxs as mr}from"react/jsx-runtime";function Qc({action:e,groups:o,busy:i}){let[r,t]=yf(!1),n=Xc(null),c=Xc(null),s=vf(),p=i||o.every(f=>f.options.every(u=>u.disabled));return xf(()=>{if(!r)return;let f=u=>{n.current?.contains(u.target)||t(!1)};return window.addEventListener("pointerdown",f),()=>window.removeEventListener("pointerdown",f)},[r]),mr("div",{className:"bb-exportMenuWrapper",ref:n,onKeyDown:f=>{f.key!=="Escape"||!r||(f.preventDefault(),f.stopPropagation(),t(!1),c.current?.focus())},children:[mr("button",{ref:c,type:"button",className:e==="Export"?"bb-button bb-button--primary":"bb-barButton",disabled:p,"aria-busy":i||void 0,onClick:()=>t(f=>!f),title:`${e} files`,"aria-label":`${e} files`,"aria-expanded":r,"aria-controls":r?s:void 0,children:[e==="Import"?Nt(Mf,{size:14,"aria-hidden":"true"}):Nt(Sf,{size:14,"aria-hidden":"true"}),e,Nt(wf,{size:12})]}),r&&Nt("div",{className:"bb-exportMenu",id:s,role:"group","aria-label":`${e} options`,children:o.map((f,u)=>mr("div",{className:"bb-fileMenuScope",children:[Nt("div",{className:"bb-exportMenuTitle",children:f.title}),Nt("p",{className:"bb-exportMenuDescription",id:`${s}-${u}`,children:f.description}),f.options.map(h=>mr("button",{type:"button",className:"bb-exportMenuItem",disabled:h.disabled||i,"aria-label":`${e} ${h.label}`,"aria-describedby":`${s}-${u}`,onClick:()=>{t(!1),h.run()},children:[h.icon,h.label]},h.label))]},f.title))})]})}function ep(e,o,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:Nt(kf,{size:14}),disabled:e==="Import"?i.importDisabled:i.exportDisabled,run:e==="Import"?i.onImport:i.onExport}]}]:[],...o.map(r=>({title:r.title,description:r.description,options:e==="Import"?[{label:`${r.title} JSON`,icon:Nt(Zc,{size:14}),disabled:r.importDisabled,run:r.onImport}]:[{label:`${r.title} JSON`,icon:Nt(Zc,{size:14}),disabled:r.exportDisabled,run:r.onExportJson},{label:`${r.title} TypeScript`,icon:Nt(Cf,{size:14}),disabled:r.exportDisabled,run:r.onExportTs}]}))]}function tp({scopes:e,sceneBundle:o,busy:i}){return Nt(Qc,{action:"Export",groups:ep("Export",e,o),busy:i})}function op({scopes:e,sceneBundle:o,busy:i}){return Nt(Qc,{action:"Import",groups:ep("Import",e,o),busy:i})}import{Box as Pf,ChevronDown as Bf,CodeXml as Tf,Maximize2 as Rf,MousePointer2 as Nf,Move3d as Af,Redo2 as Of,Rotate3d as Ef,Search as jf,SquareSplitHorizontal as If,Undo2 as zf}from"lucide-react";import{jsx as we,jsxs as Dn}from"react/jsx-runtime";var fr=[{id:"select",label:"Select",shortcut:"V",icon:we(Nf,{size:15})},{id:"move",label:"Move",shortcut:"G",icon:we(Af,{size:15})},{id:"rotate",label:"Rotate",shortcut:"R",icon:we(Ef,{size:15})},{id:"scale",label:"Scale",shortcut:"T",icon:we(Rf,{size:15})}],Df=typeof navigator<"u"&&/Mac|iPhone|iPad/.test(navigator.platform)?"\u2318K":"Ctrl K";function np({modelName:e,modelMenu:o,canUndo:i,canRedo:r,undoTarget:t,onUndo:n,onRedo:c,tool:s,onToolChange:p,space:f,onSpaceChange:u,hasModel:h,compareOpen:m,onToggleCompare:C,codeOpen:B,onToggleCode:w,onOpenCommands:P,start:v,xrToolsSlot:d,fileActions:x}){return Dn("header",{className:"bb-topBar",children:[we("span",{className:"bb-topBarLogo",role:"img","aria-label":"Binding Builder",children:we(Pf,{size:14,"aria-hidden":"true"})}),o?we(ai,{label:e,title:"Model actions",children:o}):we("span",{className:"bb-topBarModel",children:e}),v,we("span",{className:"bb-topBarDivider"}),we("button",{type:"button",className:"bb-toolButton",disabled:!i,onClick:n,title:`Undo ${t} change (Cmd/Ctrl+Z)`,"aria-label":`Undo ${t} change`,children:we(zf,{size:15})}),we("button",{type:"button",className:"bb-toolButton",disabled:!r,onClick:c,title:`Redo ${t} change (Cmd/Ctrl+Shift+Z)`,"aria-label":`Redo ${t} change`,children:we(Of,{size:15})}),we("span",{className:"bb-topBarDivider"}),we("div",{className:"bb-toolGroup",role:"radiogroup","aria-label":"Transform tool",children:fr.map(b=>we("button",{type:"button",role:"radio","aria-checked":s===b.id,"aria-label":`${b.label} tool`,disabled:!h,className:`bb-toolButton ${s===b.id?"bb-toolButton--active":""}`,onClick:()=>p(b.id),title:`${b.label} (${b.shortcut})`,children:b.icon},b.id))}),Dn("label",{className:"bb-topBarSelect",title:"Transform axes",children:[we("span",{className:"bb-visuallyHidden",children:"Transform axes"}),Dn("select",{value:f,onChange:b=>u(b.target.value),children:[we("option",{value:"world",children:"World"}),we("option",{value:"local",children:"Local"})]}),we(Bf,{size:12,"aria-hidden":"true"})]}),we("span",{className:"bb-topBarSpacer"}),Dn("button",{type:"button",className:"bb-commandButton",onClick:P,"aria-keyshortcuts":"Meta+K Control+K",children:[we(jf,{size:13,"aria-hidden":"true"}),we("span",{children:"Search settings"}),we("kbd",{children:Df})]}),we("span",{className:"bb-topBarSpacer"}),we("span",{ref:d,className:"bb-topBarXR"}),h?Dn("button",{type:"button",className:`bb-barButton ${m?"bb-barButton--active":""}`,onClick:C,"aria-pressed":m,title:"Drag a divider across the preview to see it before and after your changes",children:[we(If,{size:14,"aria-hidden":"true"}),"Compare"]}):null,Dn("button",{type:"button",className:`bb-barButton ${B?"bb-barButton--active":""}`,onClick:w,"aria-pressed":B,title:"Show the code this editor produces",children:[we(Tf,{size:14,"aria-hidden":"true"}),"Code"]}),x]})}import{useCallback as ip,useRef as Lf,useState as rp}from"react";import{Copy as Ff}from"lucide-react";async function Ln(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}import{Fragment as $f,jsx as Eo,jsxs as tn}from"react/jsx-runtime";function ap(){let[e,o]=rp(null),[i,r]=rp(null),t=Lf(null),n=ip(s=>{let f=s.target.closest?.("[data-ri-path]")?.dataset.riPath??null;f!==t.current&&(t.current=f,o(f))},[]),c=ip(s=>{let p=s.target.closest?.("[data-ri-path]");p?.dataset.riPath&&(s.preventDefault(),r({x:s.clientX,y:s.clientY,path:p.dataset.riPath}))},[]);return{path:e,menu:i,closeMenu:()=>r(null),onMouseOver:n,onContextMenu:c}}function sp({x:e,y:o,path:i,onClose:r}){return Eo("div",{className:"bb-pathMenuScrim",onPointerDown:r,onContextMenu:t=>{t.preventDefault(),r()},children:tn("div",{className:"bb-pathMenu",style:{left:e,top:o},role:"menu",onPointerDown:t=>t.stopPropagation(),children:[tn("button",{type:"button",role:"menuitem",autoFocus:!0,onKeyDown:t=>{t.key==="Escape"&&r()},onClick:()=>{Ln(i),r()},children:[Eo(Ff,{size:13,"aria-hidden":"true"}),"Copy path"]}),Eo("code",{children:i})]})})}function Hf({path:e}){let o=e.lastIndexOf(".");return tn($f,{children:[e.slice(0,o+1),Eo("em",{children:e.slice(o+1)})]})}function lp({saveState:e,objectCount:o,selectedCount:i,path:r,hints:t}){return tn("footer",{className:"bb-statusBar",children:[e?tn("span",{className:"bb-statusSave",children:[Eo("i",{"aria-hidden":"true"}),e]}):null,tn("span",{children:[o," ",o===1?"object":"objects"]}),i>0?tn("span",{children:[i," selected"]}):null,Eo("span",{className:"bb-statusPath","aria-live":"off",children:r?Eo(Hf,{path:r}):null}),Eo("span",{className:"bb-statusHints",children:t})]})}import{jsx as Uf}from"react/jsx-runtime";function ui({orientation:e,label:o,onPointerDown:i,onKeyDown:r}){return Uf("div",{className:`bb-resizer bb-resizer--${e}`,role:"separator","aria-orientation":e,"aria-label":o,tabIndex:0,onPointerDown:i,onKeyDown:r})}import{useCallback as Fa,useEffect as Vf,useRef as _f,useState as Kf}from"react";var cp="react-immersive:editor-panels";function dp(){try{return JSON.parse(localStorage.getItem(cp)??"{}")}catch{return{}}}function hr(e,{size:o,min:i,max:r,edge:t,open:n=!0}){let[c,s]=Kf(()=>{let m=dp()[e];return{size:m&&Number.isFinite(m.size)?Math.min(r,Math.max(i,m.size)):o,open:m?.open??n}}),p=_f(c);p.current=c,Vf(()=>{try{localStorage.setItem(cp,JSON.stringify({...dp(),[e]:c}))}catch{}},[e,c]);let f=Fa(m=>s(C=>({...C,open:m})),[]),u=Fa(m=>{if(m.button!==0)return;m.preventDefault();let C=m.currentTarget;C.setPointerCapture(m.pointerId);let B=t==="top"?m.clientY:m.clientX,w=p.current.size,P=t==="right"?1:-1,v=x=>{let b=t==="top"?x.clientY:x.clientX,N=Math.min(r,Math.max(i,w+(b-B)*P));s(A=>({...A,size:N}))},d=()=>{C.removeEventListener("pointermove",v),C.removeEventListener("pointerup",d),C.removeEventListener("pointercancel",d)};C.addEventListener("pointermove",v),C.addEventListener("pointerup",d),C.addEventListener("pointercancel",d)},[t,i,r]),h=Fa(m=>{let C=t==="top"?"ArrowUp":t==="right"?"ArrowRight":"ArrowLeft",B=t==="top"?"ArrowDown":t==="right"?"ArrowLeft":"ArrowRight";if(m.key!==C&&m.key!==B)return;m.preventDefault(),m.stopPropagation();let w=(m.key===C?1:-1)*16;s(P=>({...P,size:Math.min(r,Math.max(i,P.size+w))}))},[t,i,r]);return{size:c.size,open:c.open,setOpen:f,startResize:u,onResizeKey:h}}import{useEffect as Gf}from"react";import{X as qf}from"lucide-react";import{jsx as Ha,jsxs as Wf}from"react/jsx-runtime";function pp({toast:e,onDismiss:o}){return Gf(()=>{if(!e||e.tone!=="success")return;let i=window.setTimeout(o,3e3);return()=>window.clearTimeout(i)},[e,o]),e?Wf("div",{className:`bb-toast bb-toast--${e.tone}`,role:e.tone==="error"?"alert":"status",children:[Ha("span",{children:e.text}),Ha("button",{type:"button","aria-label":"Dismiss message",onClick:o,children:Ha(qf,{size:13})})]}):null}import{memo as Yf,useMemo as Jf,useState as bp}from"react";import{Check as Xf,Copy as Zf,X as Qf}from"lucide-react";function bi(e){return JSON.stringify(e,null,2)}function xr(e){return['import { defineObjectBindings } from "@liveroom-tech/react-immersive/utils";',"",`export const objectBindings = defineObjectBindings(${JSON.stringify(e,null,2)});`,""].join(`
2
- `)}function vr(e){return JSON.stringify(e,null,2)}function yr(e){return['import type { SceneConfig } from "@liveroom-tech/react-immersive/utils";',"",`export const sceneConfig: SceneConfig = ${JSON.stringify(e,null,2)};`,""].join(`
3
- `)}function up(e,o,i){Pn(new Blob([o],{type:i}),e)}function $a(e){return JSON.stringify(e??{},null,2)}function Ua(e){return`[${e[0].toFixed(3)}, ${e[1].toFixed(3)}, ${e[2].toFixed(3)}]`}import{jsx as $t,jsxs as gp}from"react/jsx-runtime";var eh={model:["model","wireframe"],camera:["camera"],world:["environment","background","groundShadows"],lighting:["lighting","shadows"],postProcessing:["postProcessing"],rules:["styleRules"],product:["product"]};function th(e){return!e||typeof e!="object"?e:Object.fromEntries(Object.entries(e).filter(([,o])=>o?.enabled))}var mp=Yf(function({scope:o,selectedKey:i,selectedBinding:r,sceneConfig:t,sceneTab:n,onClose:c}){let[s,p]=bp("ts"),[f,u]=bp(!1),{preview:h,full:m,caption:C}=Jf(()=>{if(o==="object"){if(!i||!r)return{preview:"",full:"",caption:"Select an object to see its binding."};let P={[i]:r};return{preview:bi(P),full:s==="ts"?xr(P):bi(P),caption:"objectBindings"}}let B=eh[n]??[],w=Object.fromEntries(B.map(P=>[P,P==="postProcessing"?th(t[P]):t[P]]));return{preview:JSON.stringify(w,null,2),full:s==="ts"?yr(t):vr(t),caption:"sceneConfig"}},[o,i,r,t,n,s]);return gp("section",{className:"bb-codePanel","aria-label":"Code",children:[gp("header",{children:[$t("strong",{children:"Code"}),$t("code",{children:C}),$t("span",{className:"bb-topBarSpacer"}),$t("div",{className:"bb-codeFormat",role:"radiogroup","aria-label":"Code format",children:["ts","json"].map(B=>$t("button",{type:"button",role:"radio","aria-checked":s===B,className:s===B?"is-active":"",onClick:()=>p(B),children:B==="ts"?"TS":"JSON"},B))}),$t("button",{type:"button",className:"bb-toolButton bb-toolButton--small",disabled:!m,title:o==="scene"?"Copy the whole scene config":"Copy this binding","aria-label":o==="scene"?"Copy the whole scene config":"Copy this binding",onClick:async()=>{await Ln(m),u(!0),window.setTimeout(()=>u(!1),1500)},children:f?$t(Xf,{size:13}):$t(Zf,{size:13})}),$t("button",{type:"button",className:"bb-toolButton bb-toolButton--small","aria-label":"Close code panel",onClick:c,children:$t(Qf,{size:13})})]}),$t("pre",{tabIndex:0,children:h})]})});import{useEffect as Va,useMemo as oh,useRef as hp,useState as fp}from"react";import{Search as nh}from"lucide-react";import{jsx as Ut,jsxs as on}from"react/jsx-runtime";function ih(e,o){let i=e.label.toLowerCase(),r=`${i} ${e.hint} ${e.keywords??""}`.toLowerCase(),t=0;for(let n of o){if(!r.includes(n))return-1;t+=i.startsWith(n)?3:i.includes(n)?2:1}return t}function xp({commands:e,onClose:o}){let[i,r]=fp(""),[t,n]=fp(0),c=hp(null),s=oh(()=>{let f=i.toLowerCase().split(/\s+/).filter(Boolean);return f.length?e.map(u=>({command:u,value:ih(u,f)})).filter(u=>u.value>=0).sort((u,h)=>h.value-u.value).slice(0,40).map(u=>u.command):e.slice(0,40)},[e,i]);Va(()=>n(0),[i]),Va(()=>{c.current?.children[t]?.scrollIntoView({block:"nearest"})},[t]);let p=f=>{f&&(o(),f.run())};return Ut("div",{className:"bb-paletteBackdrop",onMouseDown:f=>{f.target===f.currentTarget&&o()},children:on("div",{className:"bb-palette",role:"dialog","aria-modal":"true","aria-label":"Search settings",children:[on("label",{className:"bb-paletteSearch",children:[Ut(nh,{size:14,"aria-hidden":"true"}),Ut("input",{autoFocus:!0,role:"combobox","aria-expanded":"true","aria-controls":"bb-paletteList","aria-activedescendant":s[t]?`bb-palette-${s[t].id}`:void 0,"aria-label":"Search settings and commands",placeholder:"Search settings and commands",value:i,onChange:f=>r(f.target.value),onKeyDown:f=>{f.key==="ArrowDown"&&(f.preventDefault(),n(u=>Math.min(s.length-1,u+1))),f.key==="ArrowUp"&&(f.preventDefault(),n(u=>Math.max(0,u-1))),f.key==="Enter"&&(f.preventDefault(),p(s[t])),f.key==="Escape"&&(f.preventDefault(),f.stopPropagation(),o())}})]}),on("div",{className:"bb-paletteList",id:"bb-paletteList",role:"listbox",ref:c,children:[s.map((f,u)=>on("button",{id:`bb-palette-${f.id}`,type:"button",role:"option","aria-selected":u===t,tabIndex:-1,className:u===t?"is-active":"",onMouseMove:()=>n(u),onClick:()=>p(f),children:[Ut("span",{children:f.label}),f.shortcut?Ut("kbd",{children:f.shortcut}):null,Ut("small",{children:f.hint})]},f.id)),s.length?null:on("p",{children:["Nothing matches \u201C",i,"\u201D."]})]})]})})}function vp({onClose:e}){let o=hp(null);return Va(()=>o.current?.focus(),[]),Ut("div",{className:"bb-paletteBackdrop",onMouseDown:r=>{r.target===r.currentTarget&&e()},children:Ut("div",{ref:o,tabIndex:-1,className:"bb-shortcuts",role:"dialog","aria-modal":"true","aria-label":"Keyboard shortcuts",onKeyDown:r=>{(r.key==="Escape"||r.key==="?")&&(r.preventDefault(),r.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(([r,t])=>on("section",{children:[Ut("h4",{children:r}),t.map(([n,c])=>on("div",{children:[Ut("span",{children:c}),Ut("kbd",{children:n})]},c))]},r))})})}var ze=(e,o)=>({panel:"object",tab:e,section:o}),me=(e,o)=>({panel:"scene",tab:e,section:o}),yp=[{label:"Object ID",hint:"Object \u203A General",keywords:"identity id modelObjectId",where:ze("general","Identity")},{label:"Label, type, status, group, tags",hint:"Object \u203A General",keywords:"basics selectable hoverable visible",where:ze("general","Basics")},{label:"Position, rotation, scale",hint:"Object \u203A General",keywords:"transform move pivot",where:ze("general","Transform")},{label:"Saved view",hint:"Object \u203A General",keywords:"camera position cameraState",where:ze("general","Saved view")},{label:"Material presets",hint:"Object \u203A Material",keywords:"wood metal glass plastic",where:ze("material")},{label:"Base color",hint:"Object \u203A Material",keywords:"pbr albedo texture metalness baseColor",where:ze("material","Surface")},{label:"Roughness",hint:"Object \u203A Material",keywords:"glossiness matte shiny",where:ze("material","Roughness")},{label:"Opacity",hint:"Object \u203A Material",keywords:"alpha transparency blending",where:ze("material","Opacity")},{label:"Emission",hint:"Object \u203A Material",keywords:"emissive glow",where:ze("material","Emission")},{label:"Normal and bump maps",hint:"Object \u203A Material",keywords:"normalMap bumpMap",where:ze("material","Normal and bump")},{label:"Displacement",hint:"Object \u203A Material",keywords:"height map",where:ze("material","Displacement")},{label:"Ambient occlusion map",hint:"Object \u203A Material",keywords:"aoMap",where:ze("material","Ambient occlusion")},{label:"Clearcoat",hint:"Object \u203A Material",keywords:"lacquer gloss layer",where:ze("material","Clearcoat")},{label:"Sheen",hint:"Object \u203A Material",keywords:"fabric velvet",where:ze("material","Sheen")},{label:"Anisotropy",hint:"Object \u203A Material",keywords:"brushed metal",where:ze("material","Anisotropy")},{label:"Transmission and volume",hint:"Object \u203A Material",keywords:"glass thickness attenuation",where:ze("material","Transmission and volume")},{label:"Faces",hint:"Object \u203A Material",keywords:"side double backface",where:ze("material","Faces")},{label:"Decals",hint:"Object \u203A Decals",keywords:"logo text image print",where:ze("decals")},{label:"Actions",hint:"Object \u203A Actions",keywords:"onAction button command",where:ze("actions")},{label:"Metrics",hint:"Object \u203A Data",keywords:"json",where:ze("data","Metrics")},{label:"Metadata",hint:"Object \u203A Data",keywords:"json",where:ze("data","Metadata")},{label:"Model rotation",hint:"Scene \u203A Model",keywords:"straighten orient",where:me("model","Display")},{label:"Renderer and shading",hint:"Scene \u203A Model",keywords:"pbr matcap uv checker lit unlit normals",where:me("model","Display")},{label:"Material variants",hint:"Scene \u203A Model",keywords:"KHR_materials_variants",where:me("model","Display")},{label:"Auto rotate",hint:"Scene \u203A Model",keywords:"turntable spin",where:me("model","Auto rotate")},{label:"Wireframe",hint:"Scene \u203A Model",where:me("model","Wireframe")},{label:"Diagnostics",hint:"Scene \u203A Model",keywords:"asset statistics triangles textures",where:me("model","Diagnostics")},{label:"Field of view",hint:"Scene \u203A Camera",keywords:"fov lens",where:me("camera","Lens")},{label:"Environment",hint:"Scene \u203A World",keywords:"hdri preset intensity rotation ibl",where:me("world","Environment")},{label:"Environment shadow",hint:"Scene \u203A World",keywords:"shadowLight",where:me("world","Environment shadow")},{label:"Background",hint:"Scene \u203A World",keywords:"color image environment",where:me("world","Background")},{label:"Ground shadows",hint:"Scene \u203A World",keywords:"contact catcher",where:me("world","Ground shadows")},{label:"Lights",hint:"Scene \u203A Lights",keywords:"directional point spot hemisphere",where:me("lighting","Lights")},{label:"Shadows",hint:"Scene \u203A Lights",keywords:"map size bias softness",where:me("lighting","Shadows")},{label:"Effects",hint:"Scene \u203A Effects",keywords:"post processing bloom ssao tone mapping vignette depth of field",where:me("postProcessing")},{label:"Tone mapping",hint:"Scene \u203A Effects",keywords:"post processing effect aces filmic exposure",where:me("postProcessing","Tone mapping")},{label:"Brightness and contrast",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:me("postProcessing","Brightness and contrast")},{label:"Hue and saturation",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:me("postProcessing","Hue and saturation")},{label:"Vignette",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:me("postProcessing","Vignette")},{label:"Bloom",hint:"Scene \u203A Effects",keywords:"post processing effect glow threshold",where:me("postProcessing","Bloom")},{label:"Ambient occlusion (SSAO)",hint:"Scene \u203A Effects",keywords:"post processing effect ssao",where:me("postProcessing","Ambient occlusion")},{label:"Depth of field",hint:"Scene \u203A Effects",keywords:"post processing effect bokeh blur focus",where:me("postProcessing","Depth of field")},{label:"God rays",hint:"Scene \u203A Effects",keywords:"post processing effect sun",where:me("postProcessing","God rays")},{label:"Lens flare",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:me("postProcessing","Lens flare")},{label:"Outline",hint:"Scene \u203A Effects",keywords:"post processing effect edge",where:me("postProcessing","Outline")},{label:"Anti-aliasing (SMAA)",hint:"Scene \u203A Effects",keywords:"post processing effect smaa",where:me("postProcessing","Anti-aliasing")},{label:"Chromatic aberration",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:me("postProcessing","Chromatic aberration")},{label:"Glitch",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:me("postProcessing","Glitch")},{label:"Noise",hint:"Scene \u203A Effects",keywords:"post processing effect grain",where:me("postProcessing","Noise")},{label:"Pixelation",hint:"Scene \u203A Effects",keywords:"post processing effect ",where:me("postProcessing","Pixelation")},{label:"Section cut",hint:"Scene \u203A Model",keywords:"clip plane box slice",where:me("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:me("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 wp(e){requestAnimationFrame(()=>{let o=document.querySelector(`.bb-root [data-ri-section="${CSS.escape(e)}"]`);if(!o)return;let i=o.querySelector('button[aria-expanded="false"]');i?.closest("[data-ri-section]")===o&&i.click(),o.scrollIntoView({block:"nearest"}),o.classList.add("bb-flash"),window.setTimeout(()=>o.classList.remove("bb-flash"),900)})}import{useEffect as ph,useRef as uh,useState as wr}from"react";import{Lock as bh,Plus as gh,Trash2 as mh}from"lucide-react";import{RotateCcw as rh}from"lucide-react";import{jsx as gi}from"react/jsx-runtime";function vt({panelKey:e,title:o,tooltip:i,toggleLabel:r,controls:t,children:n,requiredTier:c,core:s=!1}){let{openMaterialPanels:p,materialPanelEnabled:f,onToggleMaterialPanel:u,onSetMaterialPanelState:h}=t,m=c?.locked??!1;return t.visibleLayers.has(e)?gi(Jc,{title:o,tooltip:i,disabled:m||!s&&!f[e],open:p[e],onToggle:()=>u(e),trailing:s?gi("button",{type:"button",className:"se-iconButton",title:`Clear ${o.toLowerCase()} overrides`,"aria-label":`Clear ${o.toLowerCase()} overrides`,onClick:()=>h(e,!1),children:gi(rh,{size:12})}):gi(de,{checked:!m&&f[e],onChange:m?()=>{}:C=>h(e,C),label:r??`Toggle ${o}`}),children:m&&c?gi(Ye,{requiredTier:c.tier,feature:o}):n}):null}import{createContext as ah,useContext as sh,useRef as lh}from"react";import{FileUp as dh}from"lucide-react";import{jsx as De,jsxs as jo}from"react/jsx-runtime";var _a=ah(null);function $e({label:e,value:o,placeholder:i,onChange:r,path:t}){let n=lh(null),c=sh(_a);return jo("div",{className:"bb-field bb-field--row","data-ri-path":t,children:[De("label",{className:"bb-label",title:e,children:e}),jo("div",{className:"bb-fileField",title:c??void 0,children:[De("input",{className:"bb-input bb-fileField-input",placeholder:i,value:o,disabled:!!c&&!o,onChange:s=>{let p=s.target.value;!p&&o&&ti(o),r(p)}}),De("button",{type:"button",className:"bb-fileFieldButton",disabled:!!c,onClick:()=>n.current?.click(),"aria-label":`Select file for ${e}`,title:`Select file for ${e}`,children:De(dh,{size:13})}),De("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 f=Cn(p);o&&o!==f&&ti(o),Ht(f,URL.createObjectURL(p)),r(f),s.target.value=""}})]})]})}function Io({label:e,value:o,fallback:i="#ffffff",onChange:r,path:t}){return jo("div",{className:"bb-field bb-field--row","data-ri-path":t,children:[De("span",{className:"bb-label",children:e}),De(Dd,{label:e,value:o||i,onChange:r})]})}function mi({label:e,checked:o,onChange:i,path:r}){return jo("label",{className:"bb-field bb-field--row","data-ri-path":r,children:[De("span",{className:"bb-label",title:e,children:e}),De("span",{className:"rui-checkCell",children:De("input",{type:"checkbox",checked:o,onChange:t=>i(t.target.checked)})})]})}function Sp({label:e,value:o,min:i,max:r,step:t,placeholder:n,disabled:c,onChange:s,path:p}){return jo("div",{className:"bb-field bb-field--row","data-ri-path":p,children:[De("label",{className:"bb-label",title:e,children:e}),De("input",{className:"bb-input",type:"number",min:i,max:r,step:t,placeholder:n,disabled:c,value:o??"",onChange:f=>s(f.target.value===""?void 0:Number(f.target.value))})]})}function ch(e,o){let i=o<1?Math.ceil(-Math.log10(o)):0,r=10**Math.max(i,0);return Math.round(e*r)/r}function Ka({label:e,value:o,min:i,max:r,step:t=.01,disabled:n,onChange:c,path:s}){let p=o??0,f=h=>{let m=h;return i!==void 0&&(m=Math.max(i,m)),r!==void 0&&(m=Math.min(r,m)),m},u=Id({value:p,step:t,min:i,max:r,disabled:n,onChange:h=>c(ch(h,t))});return jo("div",{className:"bb-field bb-field--row","data-ri-path":s,children:[De("label",{className:"bb-label bb-label--scrub",title:"Drag to change",...u,children:e}),De("input",{className:"bb-input",type:"number",min:i,max:r,step:t,disabled:n,value:p,onChange:h=>{h.target.value!==""&&c(f(Number(h.target.value)))}})]})}function Fn({label:e,value:o,options:i,onChange:r,path:t}){return jo("div",{className:"bb-field bb-field--row","data-ri-path":t,children:[De("label",{className:"bb-label",title:e,children:e}),i.length<=3?De("div",{className:"se-segmentedControl",children:i.map(n=>De("button",{type:"button",className:`se-segmentedOption ${n===o?"se-segmentedOption--active":""}`,onClick:()=>r(n),children:n.charAt(0).toUpperCase()+n.slice(1)},n))}):De("select",{className:"bb-select",value:o,onChange:n=>r(n.target.value),children:i.map(n=>De("option",{value:n,children:n.charAt(0).toUpperCase()+n.slice(1)},n))})]})}function Se({label:e,value:o,min:i,max:r,step:t,onChange:n,path:c}){return jo("div",{className:"bb-field bb-field--row","data-ri-path":c,children:[De("span",{className:"bb-label",children:e}),De(zd,{label:e,value:o??i,unset:o===void 0,min:i,max:r,step:t,onChange:n})]})}import{Fragment as Mp,jsx as L,jsxs as je}from"react/jsx-runtime";var kp="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.",Cp=[{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 Pp({selectedItem:e,selectedMaterial:o,pbrWorkflow:i,onPbrWorkflowChange:r,openMaterialPanels:t,materialPanelEnabled:n,onToggleMaterialPanel:c,onSetMaterialPanelState:s,updateSelectedMaterial:p,setSelectedTexturePath:f,isTexturePositioningEnabled:u,onConfirmTexturePosition:h,takesImage:m=!0}){let{tier:C}=lt(),B={tier:"starter",locked:!st(C,"advancedMaterials")},[w,P]=wr(()=>new Set),[v,d]=wr(!1),x=uh(null);Bn([x],()=>d(!1),v),ph(()=>P(new Set),[e]);let b=new Set(Cp.filter(M=>M.core||n[M.key]||w.has(M.key)).map(M=>M.key)),N=Cp.filter(M=>!b.has(M.key)),A=M=>{d(!1),P(E=>new Set(E).add(M)),s(M,!0),t[M]||c(M)},K={openMaterialPanels:t,materialPanelEnabled:n,onToggleMaterialPanel:c,onSetMaterialPanelState:s,visibleLayers:b},[T,z]=wr("roughness"),[y,Q]=wr("factor"),G=(M,E)=>{p(e,Ce=>{if(!Ce?.texture?.path)return Ce??{};let Xe=Ce.texture.offset??[0,0],X=[Xe[0],Xe[1]];return X[M]=E,{...Ce,texture:{...Ce.texture,offset:X}}})},ee=M=>{p(e,E=>{if(!E?.texture?.path)return E??{};let Ce=(M%360+360)%360;return{...E,texture:{...E.texture,rotation:Ce*Math.PI/180}}})},le=()=>{f(e,"texture","")};return je(_a.Provider,{value:m?null:kp,children:[m?null:L("p",{className:"bb-note bb-materialNotice",children:kp}),L(vt,{panelKey:"pbr",core:!0,title:"Surface",tooltip:"Controls the base color and workflow used for physically based shading.",controls:K,children:je("div",{className:"bb-grid",children:[L(Fn,{label:"Workflow",value:i,options:["metalness","specular"],onChange:r}),L($e,{path:"objectBindings[\u2026].style.material.texture.path",label:i==="specular"?"Albedo map":"Base map",placeholder:"materials/oak-wood.jpg",value:o?.texture?.path??"",onChange:M=>f(e,"texture",M)}),o?.texture?.path?je("div",{className:"rui-group",children:[je("div",{className:"rui-groupHeader",children:[L("span",{children:"Texture position"}),L("button",{type:"button",className:"se-iconButton",onClick:le,title:"Remove the texture and its position","aria-label":"Remove the texture and its position",children:L(mh,{size:13})})]}),je("div",{className:"bb-grid",children:[L(Ka,{path:"objectBindings[\u2026].style.material.texture.offset",label:"Offset X",value:o?.texture?.offset?.[0]??0,step:.01,onChange:M=>G(0,M)}),L(Ka,{path:"objectBindings[\u2026].style.material.texture.offset",label:"Offset Y",value:o?.texture?.offset?.[1]??0,step:.01,onChange:M=>G(1,M)})]}),L(Se,{label:"Rotation",value:((o?.texture?.rotation??0)*180/Math.PI%360+360)%360,min:0,max:360,step:1,onChange:M=>ee(M??0)}),u?L("button",{type:"button",className:"bb-button rui-inlineButton",onClick:h,title:"Confirm this texture position and exit positioning mode",children:"Done positioning"}):L("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,L(Io,{path:"objectBindings[\u2026].style.material.baseColor",label:i==="specular"?"Albedo color":"Base color",value:o?.baseColor??"#ffffff",onChange:M=>p(e,E=>({...E,baseColor:M}))}),i==="metalness"?je(Mp,{children:[L(Se,{path:"objectBindings[\u2026].style.material.metalness",label:"Metalness",value:o?.metalness,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,metalness:M}))}),L($e,{path:"objectBindings[\u2026].style.material.metalnessMap.path",label:"Metalness map",placeholder:"materials/body-metalness.jpg",value:o?.metalnessMap?.path??"",onChange:M=>f(e,"metalnessMap",M)})]}):je(Mp,{children:[L(Se,{path:"objectBindings[\u2026].style.material.specularIntensity",label:"Specular intensity",value:o?.specularIntensity,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,specularIntensity:M}))}),L(Io,{path:"objectBindings[\u2026].style.material.specularColor",label:"Specular color",value:o?.specularColor??"#ffffff",onChange:M=>p(e,E=>({...E,specularColor:M}))}),L($e,{path:"objectBindings[\u2026].style.material.specularIntensityMap.path",label:"Intensity map",placeholder:"materials/body-specular-intensity.jpg",value:o?.specularIntensityMap?.path??"",onChange:M=>f(e,"specularIntensityMap",M)}),L($e,{path:"objectBindings[\u2026].style.material.specularColorMap.path",label:"Color map",placeholder:"materials/body-specular-color.jpg",value:o?.specularColorMap?.path??"",onChange:M=>f(e,"specularColorMap",M)})]}),L(Se,{path:"objectBindings[\u2026].style.material.reflectivity",label:"Reflectivity",value:o?.reflectivity,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,reflectivity:M}))})]})}),L(vt,{panelKey:"roughness",core:!0,title:"Roughness",tooltip:"Adjusts how matte or shiny the surface appears.",toggleLabel:"Toggle Roughness and Glossiness",controls:K,children:je("div",{className:"bb-grid",children:[L(Fn,{label:"Mode",value:T,options:["roughness","glossiness"],onChange:z}),L("div",{className:"bb-field bb-field--full",children:L("p",{className:"bb-note",children:T==="roughness"?"Roughness: 0 is glossy, 1 is matte.":"Glossiness is the inverse of roughness (glossiness = 1 \u2212 roughness)"})}),T==="roughness"?L(Se,{path:"objectBindings[\u2026].style.material.roughness",label:"Roughness",value:o?.roughness,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,roughness:M}))}):L(Se,{path:"objectBindings[\u2026].style.material.roughness",label:"Glossiness",value:o?.roughness===void 0?void 0:1-o.roughness,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,roughness:M===void 0?void 0:1-M}))}),L($e,{path:"objectBindings[\u2026].style.material.roughnessMap.path",label:T==="glossiness"?"Glossiness map":"Roughness map",placeholder:"materials/body-roughness.jpg",value:o?.roughnessMap?.path??"",onChange:M=>f(e,"roughnessMap",M)})]})}),L(vt,{panelKey:"emission",title:"Emission",tooltip:"Makes the material self-illuminated with emissive color and intensity.",controls:K,children:je("div",{className:"bb-grid",children:[L(Io,{path:"objectBindings[\u2026].style.material.emissive",label:"Color",value:o?.emissive??"#000000",fallback:"#000000",onChange:M=>p(e,E=>({...E,emissive:M}))}),L(Se,{path:"objectBindings[\u2026].style.material.emissiveIntensity",label:"Intensity",value:o?.emissiveIntensity,min:0,max:10,step:.1,onChange:M=>p(e,E=>({...E,emissiveIntensity:M}))}),L($e,{path:"objectBindings[\u2026].style.material.emissiveMap.path",label:"Map",placeholder:"materials/body-emissive.jpg",value:o?.emissiveMap?.path??"",onChange:M=>f(e,"emissiveMap",M)})]})}),L(vt,{panelKey:"opacity",core:!0,title:"Opacity",tooltip:"Controls transparency, alpha testing, and blending behavior.",controls:K,children:je("div",{className:"bb-grid",children:[L(Se,{path:"objectBindings[\u2026].style.material.opacity",label:"Opacity",value:o?.opacity,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,opacity:M}))}),L(Se,{path:"objectBindings[\u2026].style.material.alphaTest",label:"Alpha test",value:o?.alphaTest,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,alphaTest:M}))}),L($e,{path:"objectBindings[\u2026].style.material.alphaMap.path",label:"Alpha map",placeholder:"materials/body-alpha.png",value:o?.alphaMap?.path??"",onChange:M=>f(e,"alphaMap",M)}),L(Fn,{path:"objectBindings[\u2026].style.material.blendingMode",label:"Blending mode",value:o?.blendingMode??"normal",options:Rd,onChange:M=>p(e,E=>({...E,blendingMode:M}))}),L(mi,{path:"objectBindings[\u2026].style.material.alphaHash",label:"Alpha hash",checked:o?.alphaHash??!1,onChange:M=>p(e,E=>({...E,alphaHash:M}))}),L(mi,{path:"objectBindings[\u2026].style.material.dithering",label:"Dithering",checked:o?.dithering??!1,onChange:M=>p(e,E=>({...E,dithering:M}))})]})}),je(vt,{panelKey:"normalBump",title:"Normal and bump",tooltip:"Adds surface detail without changing the actual mesh shape.",toggleLabel:"Toggle Normal and Bump",controls:K,children:[je("div",{className:"bb-grid",children:[L($e,{path:"objectBindings[\u2026].style.material.normalMap.path",label:"Normal map",placeholder:"materials/body-normal.jpg",value:o?.normalMap?.path??"",onChange:M=>f(e,"normalMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.normalScale",label:"Normal scale",value:o?.normalScale,min:0,max:5,step:.01,onChange:M=>p(e,E=>({...E,normalScale:M}))}),L($e,{path:"objectBindings[\u2026].style.material.bumpMap.path",label:"Bump map",placeholder:"materials/body-bump.jpg",value:o?.bumpMap?.path??"",onChange:M=>f(e,"bumpMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.bumpScale",label:"Bump scale",value:o?.bumpScale,min:0,max:5,step:.01,onChange:M=>p(e,E=>({...E,bumpScale:M}))})]}),L(mi,{path:"objectBindings[\u2026].style.material.flipNormalY",label:"Flip normal Y",checked:o?.flipNormalY??!1,onChange:M=>p(e,E=>({...E,flipNormalY:M}))})]}),L(vt,{panelKey:"displacement",requiredTier:B,title:"Displacement",tooltip:"Offsets geometry using a texture to create real surface height.",controls:K,children:je("div",{className:"bb-grid",children:[L($e,{path:"objectBindings[\u2026].style.material.displacementMap.path",label:"Map",placeholder:"materials/body-displacement.jpg",value:o?.displacementMap?.path??"",onChange:M=>f(e,"displacementMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.displacementScale",label:"Scale",value:o?.displacementScale,min:-5,max:5,step:.01,onChange:M=>p(e,E=>({...E,displacementScale:M}))}),L(Se,{path:"objectBindings[\u2026].style.material.displacementBias",label:"Bias",value:o?.displacementBias,min:-5,max:5,step:.01,onChange:M=>p(e,E=>({...E,displacementBias:M}))})]})}),L(vt,{panelKey:"ao",title:"Ambient occlusion",tooltip:"Darkens creases and contact areas to add depth.",controls:K,children:je("div",{className:"bb-grid",children:[L($e,{path:"objectBindings[\u2026].style.material.aoMap.path",label:"Map",placeholder:"materials/body-ao.jpg",value:o?.aoMap?.path??"",onChange:M=>f(e,"aoMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.aoMapIntensity",label:"Intensity",value:o?.aoMapIntensity,min:0,max:5,step:.01,onChange:M=>p(e,E=>({...E,aoMapIntensity:M}))})]})}),je(vt,{panelKey:"clearcoat",requiredTier:B,title:"Clearcoat",tooltip:"Adds a glossy protective layer on top of the base material.",controls:K,children:[je("div",{className:"bb-grid",children:[L($e,{path:"objectBindings[\u2026].style.material.clearcoatMap.path",label:"Coat map",placeholder:"materials/body-clearcoat.jpg",value:o?.clearcoatMap?.path??"",onChange:M=>f(e,"clearcoatMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.clearcoat",label:"Clearcoat",value:o?.clearcoat,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,clearcoat:M}))}),L($e,{path:"objectBindings[\u2026].style.material.clearcoatRoughnessMap.path",label:"Roughness map",placeholder:"materials/body-clearcoat-roughness.jpg",value:o?.clearcoatRoughnessMap?.path??"",onChange:M=>f(e,"clearcoatRoughnessMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.clearcoatRoughness",label:"Roughness",value:o?.clearcoatRoughness,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,clearcoatRoughness:M}))}),L($e,{path:"objectBindings[\u2026].style.material.clearcoatNormalMap.path",label:"Normal map",placeholder:"materials/body-clearcoat-normal.jpg",value:o?.clearcoatNormalMap?.path??"",onChange:M=>f(e,"clearcoatNormalMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.clearcoatNormalScale",label:"Normal scale",value:o?.clearcoatNormalScale,min:0,max:5,step:.01,onChange:M=>p(e,E=>({...E,clearcoatNormalScale:M}))})]}),L(mi,{path:"objectBindings[\u2026].style.material.flipClearcoatNormalY",label:"Flip normal Y",checked:o?.flipClearcoatNormalY??!1,onChange:M=>p(e,E=>({...E,flipClearcoatNormalY:M}))})]}),L(vt,{panelKey:"sheen",requiredTier:B,title:"Sheen",tooltip:"Adds a soft fabric-like sheen on grazing angles.",controls:K,children:je("div",{className:"bb-grid",children:[L(Se,{path:"objectBindings[\u2026].style.material.sheen",label:"Sheen",value:o?.sheen,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,sheen:M}))}),L(Io,{path:"objectBindings[\u2026].style.material.sheenColor",label:"Color",value:o?.sheenColor??"#ffffff",onChange:M=>p(e,E=>({...E,sheenColor:M}))}),L($e,{path:"objectBindings[\u2026].style.material.sheenColorMap.path",label:"Color map",placeholder:"materials/body-sheen-color.jpg",value:o?.sheenColorMap?.path??"",onChange:M=>f(e,"sheenColorMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.sheenRoughness",label:"Roughness",value:o?.sheenRoughness,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,sheenRoughness:M}))}),L($e,{path:"objectBindings[\u2026].style.material.sheenRoughnessMap.path",label:"Roughness map",placeholder:"materials/body-sheen-roughness.jpg",value:o?.sheenRoughnessMap?.path??"",onChange:M=>f(e,"sheenRoughnessMap",M)})]})}),L(vt,{panelKey:"anisotropy",requiredTier:B,title:"Anisotropy",tooltip:"Stretches reflections in one direction for brushed or fiber-like surfaces.",controls:K,children:je("div",{className:"bb-grid",children:[L(Se,{path:"objectBindings[\u2026].style.material.anisotropy",label:"Intensity",value:o?.anisotropy,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,anisotropy:M}))}),L(Fn,{label:"Direction",value:y,options:["factor","texture"],onChange:Q}),y==="factor"?L(Se,{path:"objectBindings[\u2026].style.material.anisotropyRotation",label:"Rotation",value:o?.anisotropyRotation,min:0,max:6.28,step:.01,onChange:M=>p(e,E=>({...E,anisotropyRotation:M}))}):L($e,{path:"objectBindings[\u2026].style.material.anisotropyMap.path",label:"Map",placeholder:"materials/body-anisotropy.jpg",value:o?.anisotropyMap?.path??"",onChange:M=>f(e,"anisotropyMap",M)})]})}),L(vt,{panelKey:"transmission",requiredTier:B,title:"Transmission and volume",tooltip:"Controls glass-like transmission and how light travels through volume.",toggleLabel:"Toggle Transmission and Volume",controls:K,children:je("div",{className:"bb-grid",children:[L(Se,{path:"objectBindings[\u2026].style.material.transmission",label:"Transmission",value:o?.transmission,min:0,max:1,step:.01,onChange:M=>p(e,E=>({...E,transmission:M}))}),L($e,{path:"objectBindings[\u2026].style.material.transmissionMap.path",label:"Map",placeholder:"materials/body-transmission.jpg",value:o?.transmissionMap?.path??"",onChange:M=>f(e,"transmissionMap",M)}),L(Se,{path:"objectBindings[\u2026].style.material.thickness",label:"Thickness",value:o?.thickness,min:0,max:5,step:.01,onChange:M=>p(e,E=>({...E,thickness:M}))}),L($e,{path:"objectBindings[\u2026].style.material.thicknessMap.path",label:"Thickness map",placeholder:"materials/body-thickness.jpg",value:o?.thicknessMap?.path??"",onChange:M=>f(e,"thicknessMap",M)}),L(Io,{path:"objectBindings[\u2026].style.material.attenuationColor",label:"Volume tint",value:o?.attenuationColor??"#ffffff",onChange:M=>p(e,E=>({...E,attenuationColor:M}))}),L(Sp,{path:"objectBindings[\u2026].style.material.attenuationDistance",label:"Attenuation",value:o?.attenuationDistance,min:0,step:.01,placeholder:"Infinity when unset",onChange:M=>p(e,E=>({...E,attenuationDistance:M}))})]})}),L(vt,{panelKey:"faces",title:"Faces",tooltip:"Chooses which side of the mesh renders and how backfaces are handled.",controls:K,children:L("div",{className:"bb-grid",children:L(Fn,{path:"objectBindings[\u2026].style.material.side",label:"Side",value:o?.side??"front",options:Td,onChange:M=>p(e,E=>({...E,side:M}))})})}),N.length?je("div",{className:"se-listHeader se-listHeader--footer",ref:x,children:[je("button",{type:"button",className:"bb-button bb-button--ghost bb-button--small","aria-expanded":v,onClick:()=>d(M=>!M),children:[L(gh,{size:13,"aria-hidden":"true"}),"Add layer"]}),v?L("div",{className:"se-addMenu se-addMenu--up",role:"menu","aria-label":"Add layer",children:N.map(M=>je("button",{type:"button",role:"menuitem",onClick:()=>A(M.key),children:[L("span",{children:M.label}),M.advanced&&B.locked?L(bh,{size:12,"aria-label":"Needs an upgrade"}):null]},M.key))}):null]}):null]})}import{useRef as xh,useState as vh}from"react";import{Ban as yh,ChevronDown as wh}from"lucide-react";var Sr="default",Ga=[{id:Sr,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}}],fh=Array.from(new Set(Ga.flatMap(e=>Object.keys(e.material)))),hh=Object.fromEntries(fh.map(e=>[e,void 0]));function Bp(e){return e.id===Sr?hh:e.material}import{jsx as nn,jsxs as qa}from"react/jsx-runtime";function Tp({disabled:e,onApply:o}){let[i,r]=vh(!1),t=xh(null);return Bn([t],()=>r(!1),i),qa("div",{className:"se-field se-fieldInline bb-presetRow",ref:t,children:[nn("span",{className:"se-fieldLabel",children:"Preset"}),qa("button",{type:"button",className:"bb-presetButton",disabled:e,"aria-expanded":i,onClick:()=>r(n=>!n),children:[nn("span",{children:"Apply a preset"}),nn(wh,{size:12,"aria-hidden":"true"})]}),i?nn("div",{className:"se-addMenu bb-presetMenu",role:"menu","aria-label":"Material presets",children:Ga.map(n=>qa("button",{type:"button",role:"menuitem",onClick:()=>{r(!1),o(Bp(n))},children:[nn("span",{className:"bb-presetSwatch",style:{background:n.swatch},children:n.id===Sr?nn(yh,{size:10,"aria-hidden":"true"}):null}),nn("span",{className:"bb-presetLabel",children:n.label})]},n.id))}):null]})}import{jsx as Hn,jsxs as Wa}from"react/jsx-runtime";function Rp({selectedItem:e,selectedBinding:o,open:i,onToggle:r,updateBinding:t,idError:n}){return Hn(Je,{title:"Identity",open:i,onToggle:r,children:Wa("div",{className:"bb-grid",children:[Wa("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].modelObjectId",children:[Hn("label",{className:"bb-label",title:"The object's exact name in the model file. It can't be changed.",children:"Model object ID"}),Hn("input",{className:"bb-input bb-readonly",value:o.modelObjectId,readOnly:!0})]}),Wa("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].id",children:[Hn("label",{className:"bb-label",children:"ID"}),Hn("input",{className:`bb-input ${n?"bb-input--error":""}`,value:o.id,onChange:c=>t(e,s=>({...s,id:c.target.value}))}),n?Hn("span",{className:"bb-status bb-status--error bb-fieldFull",children:n}):null]})]})})}import{useEffect as Sh,useState as Np}from"react";import{jsx as ot,jsxs as Vt}from"react/jsx-runtime";function Ap({selectedItem:e,selectedBinding:o,open:i,onToggle:r,updateBinding:t}){let[n,c]=Np(o.group??""),[s,p]=Np(o.tags?.join(", ")??"");Sh(()=>{c(o.group??""),p(o.tags?.join(", ")??"")},[e,o.group,o.tags]);let f=()=>{t(e,h=>({...h,group:n.trim()||void 0}))},u=()=>{let h=[...new Set(s.split(",").map(m=>m.trim()).filter(Boolean))];t(e,m=>({...m,tags:h.length>0?h:void 0}))};return Vt(Je,{title:"Basics",open:i,onToggle:r,children:[Vt("div",{className:"bb-grid",children:[Vt("div",{className:"bb-field",children:[ot("label",{className:"bb-label",children:"Label"}),ot("input",{className:"bb-input",value:o.label??"",onChange:h=>t(e,m=>({...m,label:h.target.value}))})]}),Vt("div",{className:"bb-field",children:[ot("label",{className:"bb-label",children:"Type"}),ot("input",{className:"bb-input",list:"binding-type-suggestions",value:o.type??"other",onChange:h=>t(e,m=>({...m,type:h.target.value}))}),ot("datalist",{id:"binding-type-suggestions",children:Ld.map(h=>ot("option",{value:h},h))})]}),Vt("div",{className:"bb-field",children:[ot("label",{className:"bb-label",children:"Status"}),ot("select",{className:"bb-select",value:o.status??"normal",onChange:h=>t(e,m=>({...m,status:h.target.value})),children:Fd.map(h=>ot("option",{value:h,children:h},h))})]}),Vt("div",{className:"bb-field",children:[ot("label",{className:"bb-label",children:"Group"}),ot("input",{className:"bb-input",placeholder:"paint",value:n,onChange:h=>c(h.target.value),onBlur:f,onKeyDown:h=>{h.key==="Enter"&&h.currentTarget.blur()}})]}),Vt("div",{className:"bb-field",children:[ot("label",{className:"bb-label",children:"Tags"}),ot("input",{className:"bb-input",placeholder:"exterior, configurable",value:s,onChange:h=>p(h.target.value),onBlur:u,onKeyDown:h=>{h.key==="Enter"&&h.currentTarget.blur()}})]})]}),Vt("div",{className:"bb-checkboxRow",children:[Vt("label",{className:"bb-checkbox",children:[ot("input",{type:"checkbox",checked:o.selectable!==!1,onChange:h=>t(e,m=>({...m,selectable:h.target.checked}))}),"Selectable"]}),Vt("label",{className:"bb-checkbox",children:[ot("input",{type:"checkbox",checked:o.hoverable!==!1,onChange:h=>t(e,m=>({...m,hoverable:h.target.checked}))}),"Hoverable"]}),Vt("label",{className:"bb-checkbox",children:[ot("input",{type:"checkbox",checked:o.visible!==!1,onChange:h=>t(e,m=>({...m,visible:h.target.checked}))}),"Visible"]})]})]})}import{useEffect as kh,useState as Ch}from"react";import{Plus as Mh,Trash2 as Ph}from"lucide-react";import{Fragment as Th,jsx as Ue,jsxs as yt}from"react/jsx-runtime";var Op=fa.filter(e=>e.handling==="viewer"),Bh=fa.filter(e=>e.handling==="host");function Ep({selectedItem:e,selectedBinding:o,open:i,onToggle:r,updateBinding:t,takesImage:n=!0}){let[c,s]=Ch(new Set);kh(()=>{s(new Set)},[e]);let p=o.actions??[],f=(m,C)=>t(e,B=>({...B,actions:(B.actions??[]).map((w,P)=>P===m?C(w):w)})),u=m=>{t(e,C=>({...C,actions:(C.actions??[]).filter((B,w)=>w!==m)})),s(C=>{let B=new Set;return C.forEach(w=>{w<m?B.add(w):w>m&&B.add(w-1)}),B})},h=(m,C)=>s(B=>{let w=new Set(B);return C?w.add(m):w.delete(m),w});return yt(Je,{title:"Actions",open:i,onToggle:r,children:[Ue("div",{className:"bb-actionList",children:p.map((m,C)=>{let B=ir(m.id),w=c.has(C)||!B,P=m.id.trim(),v=B?null:nd(m.id),d=P.length>0&&p.some((x,b)=>b!==C&&x.id.trim()===P);return yt("div",{className:"bb-actionCard",children:[yt("div",{className:"rui-groupHeader",children:[yt("span",{children:["Action ",C+1]}),Ue("button",{type:"button",className:"se-iconButton",title:"Remove action","aria-label":`Remove action ${C+1}`,onClick:()=>u(C),children:Ue(Ph,{size:13})})]}),yt("div",{className:"bb-actionGrid",children:[yt("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].actions[\u2026].id",children:[Ue("label",{className:"bb-label",children:"ID"}),yt("select",{className:"bb-select",value:w?nr:m.id,onChange:x=>{let b=x.target.value;if(b===nr){h(C,!0);return}h(C,!1);let N=ir(b);f(C,A=>({...A,id:b,label:N&&ha(A.label)?N.label:A.label}))},children:[Ue("optgroup",{label:"Handled by the viewer",children:Op.map(x=>Ue("option",{value:x.id,children:x.id},x.id))}),Ue("optgroup",{label:"Handled by your app",children:Bh.map(x=>Ue("option",{value:x.id,children:x.id},x.id))}),Ue("option",{value:nr,children:"Custom\u2026"})]})]}),w?yt("div",{className:"bb-field bb-field--row",children:[Ue("label",{className:"bb-label",children:"Custom ID"}),Ue("input",{className:"bb-input",value:m.id,placeholder:"open-datasheet",onChange:x=>{h(C,!0),f(C,b=>({...b,id:x.target.value}))}})]}):null,yt("div",{className:"bb-field bb-field--row","data-ri-path":"objectBindings[\u2026].actions[\u2026].label",children:[Ue("label",{className:"bb-label",children:"Label"}),Ue("input",{className:"bb-input",value:m.label,onChange:x=>f(C,b=>({...b,label:x.target.value}))})]}),B?.id==="change-material"&&!n?Ue("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."}):B?Ue("span",{className:"bb-note",children:B.description}):P.length===0?Ue("span",{className:"bb-note bb-note--error",children:"An action ID is required, the button renders but can never be identified in onAction."}):yt("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.",v?yt(Th,{children:[" Did you mean ",Ue("button",{type:"button",className:"bb-linkButton",onClick:()=>{h(C,!1);let x=ir(v);f(C,b=>({...b,id:v,label:x&&ha(b.label)?x.label:b.label}))},children:v}),"?"]}):null]}),m.effects?.length?yt("span",{className:"bb-note",children:[m.effects.length," declarative effect",m.effects.length===1?"":"s",", execute with useViewerActions."]}):null,d?Ue("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)})}),Ue(co,{children:yt("button",{type:"button",className:"bb-button",onClick:()=>{let m=Op.find(C=>!p.some(B=>B.id===C.id));t(e,C=>({...C,actions:[...C.actions??[],{id:m?.id??"",label:m?.label??"New action",type:"command"}]})),m||h(p.length,!0)},children:[Ue(Mh,{size:13,"aria-hidden":"true"}),"Add action"]})})]})}import{useRef as Rh}from"react";import{Image as Nh,ImagePlus as Ah,Trash2 as Oh,Type as jp}from"lucide-react";import{Fragment as zp,jsx as Ge,jsxs as wt}from"react/jsx-runtime";var Ip=()=>`decal-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;function Dp({selectedItem:e,selectedBinding:o,open:i,onToggle:r,updateBinding:t,placement:n,onPlacementChange:c,defaultSize:s,onImageFile:p,onNudge:f}){let{tier:u}=lt(),h=Rh(null),m=o.decals??[],C=n?.nodeKey===e?n:null,B=v=>t(e,d=>({...d,decals:v.length>0?v:void 0})),w=(v,d)=>B(m.map(x=>x.id===v?{...x,...d}:x)),P=v=>{v.image&&ti(v.image),C?.decal.id===v.id&&c(null),B(m.filter(d=>d.id!==v.id))};return wt(Je,{title:"Decals",open:i,onToggle:r,tooltip:"Print a logo, image, or text on the selected object's surface.",children:[Tt(u,"decalsPerObject",m.length)?null:Ge(Ye,{requiredTier:Yo("decalsPerObject",m.length),feature:"More decals on this object"}),wt(zp,{children:[wt("div",{className:"rui-actions",children:[wt("button",{type:"button",className:"bb-button",disabled:!Tt(u,"decalsPerObject",m.length),onClick:()=>h.current?.click(),children:[Ge(Ah,{size:13,"aria-hidden":"true"})," Add image"]}),wt("button",{type:"button",className:"bb-button",disabled:!Tt(u,"decalsPerObject",m.length),onClick:()=>c({nodeKey:e,decal:{id:Ip(),text:"Your text",color:"#ffffff",size:s}}),children:[Ge(jp,{size:13,"aria-hidden":"true"})," Add text"]}),Ge("input",{ref:h,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif,image/svg+xml",className:"bb-hiddenInput",onChange:v=>{let d=v.target.files?.[0];if(v.target.value="",!d)return;let x=Cn(d);Ht(x,URL.createObjectURL(d)),p?.(x,d),c({nodeKey:e,decal:{id:Ip(),image:x,size:s}})}})]}),m.length===0&&!C?Ge("p",{className:"se-listEmpty",children:"No decals on this object yet."}):null,m.map(v=>wt("div",{className:"bb-decalCard",children:[wt("div",{className:"rui-groupHeader",children:[wt("span",{className:"rui-groupTitle",title:v.image??v.text,children:[v.image?Ge(Nh,{size:13,"aria-hidden":"true"}):Ge(jp,{size:13,"aria-hidden":"true"}),v.image??v.text]}),Ge("button",{type:"button",className:"se-iconButton",title:"Delete decal","aria-label":"Delete decal",onClick:()=>P(v),children:Ge(Oh,{size:13})})]}),Ge(id,{onNudge:d=>f(v.id,d)}),wt("div",{className:"bb-grid",children:[v.image?null:wt(zp,{children:[wt("div",{className:"bb-field bb-field--row",children:[Ge("label",{className:"bb-label",children:"Text"}),Ge("input",{className:"bb-input",value:v.text??"",onChange:d=>w(v.id,{text:d.target.value})})]}),Ge(Io,{label:"Color",variant:"input",value:v.color??"#ffffff",onChange:d=>w(v.id,{color:d})}),wt("div",{className:"bb-field bb-field--row",children:[Ge("label",{className:"bb-label",children:"Weight"}),wt("select",{className:"bb-select",value:v.fontWeight??"bold",onChange:d=>w(v.id,{fontWeight:d.target.value}),children:[Ge("option",{value:"bold",children:"Bold"}),Ge("option",{value:"normal",children:"Regular"})]})]})]}),Ge(Se,{label:"Size",value:Number(v.size.toFixed(4)),min:Number((s/20).toPrecision(2)),max:Number((s*6).toPrecision(2)),step:Number((s/50).toPrecision(1)),onChange:d=>d!==void 0&&d>0&&w(v.id,{size:d})}),Ge(Se,{label:"Rotation",value:Math.round((v.rotation??0)*180/Math.PI),min:-180,max:180,step:1,onChange:d=>w(v.id,{rotation:(d??0)*Math.PI/180})}),Ge(Se,{label:"Opacity",value:v.opacity??1,min:0,max:1,step:.05,onChange:d=>w(v.id,{opacity:d??1})})]})]},v.id))]})]})}import{MapPin as Eh,Trash2 as jh}from"lucide-react";import{jsx as St,jsxs as fi}from"react/jsx-runtime";var Ih=e=>e.map(o=>o.toFixed(2)).join(", ");function Lp({open:e,onToggle:o,cameraState:i,formattedCameraState:r,savedCameraPosition:t,onSaveCameraPosition:n,onGoToSavedCamera:c,onClearSavedCamera:s,onResetView:p,onFitScene:f}){let u=t?.position&&t?.target?t:null;return fi(Je,{title:"Saved view",open:e,onToggle:o,tooltip:"Stores the current camera for this object, so selecting it flies there.",children:[St(Tn,{label:"Camera",children:St("code",{className:"rui-readout",children:i?r?.position:"Move the camera"})}),St(Tn,{label:"Looking at",children:St("code",{className:"rui-readout",children:i?r?.target:"\u2013"})}),u?fi("div",{className:"rui-listRow rui-listRow--saved",children:[fi("span",{className:"rui-listRowMain",children:[St("span",{className:"rui-listRowTitle",children:"Saved view"}),St("code",{className:"rui-listRowMeta",children:Ih(u.position)})]}),fi("span",{className:"rui-listRowActions rui-listRowActions--visible",children:[St("button",{type:"button",className:"se-iconButton",onClick:c,title:"Fly to the saved view","aria-label":"Fly to the saved view",children:St(Eh,{size:13})}),St("button",{type:"button",className:"se-iconButton",onClick:s,title:"Delete saved view","aria-label":"Delete saved view",children:St(jh,{size:13})})]})]}):null,fi(co,{children:[St("button",{type:"button",className:"bb-button",onClick:n,disabled:!i,children:u?"Update view":"Save view"}),St("button",{type:"button",className:"bb-button",onClick:p,children:"Reset camera"}),St("button",{type:"button",className:"bb-button",onClick:f,children:"Fit scene"})]})]})}import{useLayoutEffect as zh,useRef as Dh,useState as Lh}from"react";import{RotateCcw as Fh}from"lucide-react";import{jsx as nt,jsxs as rn}from"react/jsx-runtime";var Hp=["X","Y","Z"],Hh=.1,$h=.1,Fp=.01;function $p(e){let o=e%360;return o<0?o+360:o}function Uh(e){return $p(e*180/Math.PI)}function Vh(e){return e*Math.PI/180}function Ya({value:e,min:o=-1/0,max:i=1/0,step:r=.1,disabled:t=!1,onChange:n,formatValue:c=f=>Number(f.toFixed(3)),ariaLabel:s,className:p}){let f=c(e),[u,h]=Lh(String(f)),m=Dh(!1);return zh(()=>{m.current||h(String(f))},[f]),nt("input",{type:"number",className:p,step:r,min:o===-1/0?void 0:o,max:i===1/0?void 0:i,value:u,disabled:t,"aria-label":s,onFocus:()=>{m.current=!0},onChange:C=>{let B=C.target.value;if(h(B),B===""||B==="-")return;let w=Number(B);if(Number.isFinite(w)){let P=Math.max(o,Math.min(i,w));n(P)}},onBlur:()=>{m.current=!1,h(String(c(e)))}})}function _h({value:e,min:o=-1/0,max:i=1/0,step:r=.1,disabled:t=!1,onChange:n,formatValue:c=p=>Number(p.toFixed(3)),label:s}){return nt("div",{className:"bb-transformAxesGrid",children:Hp.map((p,f)=>rn("div",{className:"bb-transformAxis",children:[nt("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:p}),nt("div",{className:"bb-transformAxisControl",children:nt(Ya,{className:"se-numberInput bb-transformNumberInput",step:r,min:o,max:i,value:e[f],disabled:t,formatValue:c,ariaLabel:`${p} ${s?.toLowerCase()||""}`,onChange:u=>{let h=[...e];h[f]=u,n(h,f)}})})]},p))})}function Up({selectedItem:e,selectedBinding:o,open:i,onToggle:r,updateBinding:t,originalTransform:n,originalTransforms:c}){let s=o.transform?.rotation??n?.rotation??[0,0,0],p=o.transform?.position??n?.position??[0,0,0],f=n?.scale??[1,1,1],u=xa(o.transform?.scale??f,f),h=(v=e??"")=>c?.[v]??(v===e?n:null),m=(v,d)=>v.transform?.pivot??sd(d?.pivotLocal??[0,0,0],v.transform?.rotation??d?.rotation??[0,0,0],v.transform?.scale??d?.scale??[1,1,1],d?.rotationOrder??"XYZ",v.transform?.shear),C=(v,d)=>{e&&t(e,(x,b)=>{let N=h(b),K=[...x.transform?.rotation??N?.rotation??[0,0,0]];return K[v]=Vh($p(d)),{...x,transform:{...x.transform,rotation:K,pivot:m(x,N)}}})},B=(v,d)=>{e&&t(e,(x,b)=>{let N=h(b),K=[...x.transform?.position??N?.position??[0,0,0]];return K[v]=d,{...x,transform:{...x.transform,position:K}}})},w=v=>{if(!e)return;let d=Math.max(Fp,v);t(e,(x,b)=>{let N=h(b),A=N?.scale??[1,1,1],K=x.transform?.scale??A,T=xa(K,A),z=T>0?K:A,y=d/(T||1);return{...x,transform:{...x.transform,scale:z.map(Q=>Q*y),pivot:m(x,N)}}})},P=()=>{!e||!n||t(e,v=>{let d={...v.transform};return delete d.position,delete d.rotation,delete d.scale,delete d.pivot,delete d.shear,{...v,transform:Object.keys(d).length>0?d:void 0}})};return rn(Je,{title:"Transform",open:i,onToggle:r,tooltip:"Rotation and scale keep the object's visible center fixed. Scale preserves its proportions.",children:[rn("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.rotation",children:[nt("span",{className:"se-fieldLabel",children:"Rotation"}),nt("div",{className:"bb-transformAxesGrid",children:Hp.map((v,d)=>{let x=Math.round(Uh(s[d]));return rn("div",{className:"bb-transformAxis",children:[nt("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:v}),nt("div",{className:"bb-transformAxisControl",children:nt(Ya,{className:"se-numberInput bb-transformNumberInput",step:1,min:0,max:359,value:x,disabled:!e,formatValue:b=>Math.round(b),ariaLabel:`${v} rotation in degrees`,onChange:b=>C(d,b)})})]},v)})})]}),rn("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.position",children:[nt("span",{className:"se-fieldLabel",children:"Position"}),nt(_h,{value:p,min:-1/0,max:1/0,step:Hh,disabled:!e,label:"position",onChange:(v,d)=>B(d,v[d])})]}),rn("div",{className:"se-field se-fieldInline","data-ri-path":"objectBindings[\u2026].transform.scale",children:[nt("span",{className:"se-fieldLabel",children:"Scale"}),nt(Ya,{className:"se-numberInput bb-transformNumberInput",step:$h,min:Fp,value:u,disabled:!e,formatValue:v=>Number(v.toFixed(2)),ariaLabel:"Uniform scale factor",onChange:w})]}),nt(co,{children:rn("button",{type:"button",className:"bb-button",disabled:!e||!n,onClick:P,title:"Restore this object's position, rotation, and scale to what they were in the original model",children:[nt(Fh,{size:13,"aria-hidden":"true"}),"Restore original"]})})]})}function Vp(e,o,i){let r=e.key?o.has(e.key)?[...o]:[e.key]:e.keys;return[...new Set(r)].filter(t=>i[t]&&!i[t].removed)}function _p(e,o,i){let r=e[o],t=i.trim();return!r||r.removed||!t||r.label===t?e:{...e,[o]:{...r,label:t}}}function Kp(e,o,i){let r=o.filter(n=>e[n]&&!e[n].removed&&e[n].visible!==i);if(!r.length)return e;let t={...e};for(let n of r)t[n]={...e[n],visible:i};return t}import{memo as vx}from"react";import{useCallback as ex,useEffect as Qa,useId as tx,useLayoutEffect as es,useMemo as $n,useRef as hi,useState as an}from"react";import{Box as ox,ChevronDown as nx,ChevronRight as ix,ChevronsDownUp as rx,ChevronsUpDown as ax,EyeOff as sx,Focus as lx,Folder as dx,Lightbulb as cx,ListChecks as px,Trash2 as ux}from"lucide-react";import{useLayoutEffect as Gp,useRef as Kh,useState as Ja}from"react";import{ChevronDown as Gh,ChevronRight as qh,Copy as Wh,Eye as Yh,EyeOff as Jh,Focus as qp,ListChecks as Xh,Pencil as Zh,Trash2 as Qh}from"lucide-react";import{Fragment as Wp,jsx as tt,jsxs as mo}from"react/jsx-runtime";function Yp({x:e,y:o,name:i,objectKey:r,objectId:t,keys:n,hidden:c,isolated:s,expanded:p,onRename:f,onSetVisible:u,onDelete:h,onFocus:m,onIsolate:C,onSelectContents:B,onToggle:w,onClose:P}){let v=Kh(null),[d,x]=Ja(!1),[b,N]=Ja(i),[A,K]=Ja(!1);Gp(()=>{let y=v.current,Q=document.activeElement,G=()=>P();return window.addEventListener("resize",G),window.addEventListener("blur",G),()=>{window.removeEventListener("resize",G),window.removeEventListener("blur",G),(!document.activeElement||document.activeElement===document.body||y?.contains(document.activeElement))&&Q?.isConnected&&Q.focus({preventScroll:!0})}},[P]),Gp(()=>{let y=v.current;if(!y)return;let Q=y.getBoundingClientRect();y.style.left=`${Math.max(8,Math.min(e,window.innerWidth-Q.width-8))}px`,y.style.top=`${Math.max(8,Math.min(o,window.innerHeight-Q.height-8))}px`,d?y.querySelector("input")?.select():y.querySelector("button")?.focus()},[e,o,d,A]);let T=(y,Q,G,ee=!1)=>mo("button",{type:"button",role:"menuitem",className:ee?"bb-treeMenuDanger":void 0,onClick:()=>{P(),G()},children:[Q,y]}),z=n.length>1;return tt("div",{className:"bb-pathMenuScrim",onPointerDown:y=>{y.stopPropagation(),P()},onContextMenu:y=>{y.preventDefault(),y.stopPropagation(),P()},children:tt("div",{ref:v,className:"bb-pathMenu bb-treeMenu",style:{left:e,top:o},role:d?"dialog":"menu","aria-modal":d||void 0,"aria-label":d?`Rename ${i}`:`Actions for ${i}`,onPointerDown:y=>y.stopPropagation(),onContextMenu:y=>{y.preventDefault(),y.stopPropagation()},onKeyDown:y=>{if(y.stopPropagation(),y.key==="Escape"){y.preventDefault(),P();return}if(y.key==="Tab"){if(y.preventDefault(),!d){P();return}let le=Array.from(v.current.querySelectorAll("input, button:not(:disabled)")),M=le.indexOf(document.activeElement);le[(M+(y.shiftKey?-1:1)+le.length)%le.length]?.focus();return}if(d||!["ArrowDown","ArrowUp","Home","End"].includes(y.key))return;y.preventDefault();let Q=Array.from(v.current.querySelectorAll("[role=menuitem]")),G=Q.indexOf(document.activeElement),ee=y.key==="Home"?0:y.key==="End"?Q.length-1:(G+(y.key==="ArrowDown"?1:-1)+Q.length)%Q.length;Q[ee]?.focus()},children:d?mo("form",{onSubmit:y=>{y.preventDefault(),!(!b.trim()||!r)&&(f?.(r,b.trim()),P())},children:[mo("label",{children:["Display name",tt("input",{className:"bb-input","aria-label":"Object display name",value:b,maxLength:200,onChange:y=>N(y.target.value)})]}),mo("div",{className:"bb-treeMenuRenameActions",children:[tt("button",{type:"button",onClick:P,children:"Cancel"}),tt("button",{type:"submit",disabled:!b.trim(),children:"Save"})]})]}):mo(Wp,{children:[tt("div",{className:"bb-treeMenuTitle",children:z&&r?`${n.length} selected objects`:i}),r&&m&&T("Focus object",tt(qp,{size:13}),()=>m(r)),r&&C&&T(s?"Show all objects":"Isolate object",tt(qp,{size:13}),()=>C(s?null:r)),u&&T(`${c?"Show":"Hide"}${z?` ${n.length} objects`:""}`,c?tt(Yh,{size:13}):tt(Jh,{size:13}),()=>u(n,c)),r&&f&&mo("button",{type:"button",role:"menuitem",onClick:()=>x(!0),children:[tt(Zh,{size:13}),"Rename\u2026"]}),!r&&B&&T(`Select contents (${n.length})`,tt(Xh,{size:13}),()=>B(n)),p!==void 0&&T(p?"Collapse branch":"Expand branch",p?tt(qh,{size:13}):tt(Gh,{size:13}),w),t&&mo("button",{type:"button",role:"menuitem",onClick:async()=>{await Ln(t)?P():K(!0)},children:[tt(Wh,{size:13}),"Copy object ID"]}),A&&mo("p",{role:"status",className:"bb-treeMenuError",children:["Couldn\u2019t copy. Object ID: ",t]}),h&&mo(Wp,{children:[tt("hr",{}),T(z?`Delete ${n.length} objects\u2026`:"Delete\u2026",tt(Qh,{size:13}),()=>h(n),!0)]})]})})})}function Jp(e,o){let i=new Map(Object.entries(o).filter(([,c])=>!c.removed).map(([c,s])=>[s.modelObjectId??c,c])),r=new Set,t=new Map;for(let c of e){let s=c.objectId?i.get(c.objectId):void 0;s&&r.add(s),t.set(c.id,{id:c.id,name:c.name,key:s,children:[],keys:[]})}let n=[];for(let c of e){let s=t.get(c.id);((c.parentId?t.get(c.parentId):void 0)?.children??n).push(s)}for(let[c,s]of Object.entries(o))!s.removed&&!r.has(c)&&n.push({id:`binding:${c}`,name:s.modelObjectId??c,key:c,children:[],keys:[c]});for(let c=e.length-1;c>=0;c--){let s=t.get(e[c].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(c=>c.keys.length)}function Xp(e,o,i){let r=i.trim().toLowerCase();if(!r)return e;let t=n=>{let c=n.key?o[n.key]:void 0;if([n.name,n.key,c?.label,c?.type,c?.group,...c?.tags??[]].join(" ").toLowerCase().includes(r))return n;let p=n.children.map(t).filter(f=>!!f);return p.length?{...n,key:void 0,children:p,keys:p.flatMap(f=>f.keys)}:null};return e.map(t).filter(n=>!!n)}function Xa(e,o,i=!1){let r=[],t=e.slice().reverse().map(n=>({node:n,depth:0,parentId:null}));for(;t.length;){let n=t.pop();if(r.push(n),i||!o.has(n.node.id))for(let c=n.node.children.length-1;c>=0;c--)t.push({node:n.node.children[c],depth:n.depth+1,parentId:n.node.id})}return r}function Za(e,o){for(let i of e){if(i.key===o)return[];let r=Za(i.children,o);if(r)return[i.id,...r]}return null}function Zp(e,o,i,r,t){if(t.range){let n=i?r.indexOf(i):-1,c=r.indexOf(o);if(n>=0&&c>=0){let s=r.slice(Math.min(n,c),Math.max(n,c)+1);return[...new Set(t.additive?[...e,...s]:s)]}}return t.toggle||t.additive?e.includes(o)?e.filter(n=>n!==o):[...e,o]:[o]}import{Fragment as xx,jsx as be,jsxs as gt}from"react/jsx-runtime";var bx=[],gx=[],mx=[],fo=24;function fx({count:e,total:o,name:i,onChange:r}){let t=hi(null);return es(()=>{t.current&&(t.current.indeterminate=e>0&&e<o)},[e,o]),be("input",{ref:t,className:"bb-treeCheckbox",type:"checkbox","aria-label":`Select ${i}`,"aria-checked":e>0&&e<o?"mixed":e===o,checked:e===o&&o>0,onChange:r})}function kr({bindings:e,hierarchy:o=gx,selectedItem:i,onSelect:r,onHover:t,fill:n,isolatedItem:c,onIsolate:s,multiSelectEnabled:p=!1,multiSelectedKeys:f=bx,onSetMultiSelected:u,selectionSets:h=mx,onSelectionSetsChange:m,onToggleMultiSelect:C,onRename:B,onSetVisible:w,onDelete:P,onFocus:v}){let[d,x]=an(""),[b,N]=an(()=>new Set),[A,K]=an(""),T=hi(null),z=$n(()=>Jp(o,e),[o,e]),y=$n(()=>Xp(z,e,d),[z,e,d]),Q=$n(()=>Xa(y,b,!!d.trim()),[y,b,d]),G=$n(()=>Q.flatMap(({node:D})=>D.key?[D.key]:[]),[Q]),ee=$n(()=>y.flatMap(D=>D.keys),[y]),le=hi(null);Qa(()=>{if(le.current===i)return;let D=i?Za(z,i):null;i&&!D||(le.current=i,D?.length&&N($=>{if(!D.some(ue=>$.has(ue)))return $;let fe=new Set($);return D.forEach(ue=>fe.delete(ue)),fe}))},[i,z]);let M=$n(()=>new Set(p||f.length>0?f:i?[i]:[]),[p,f,i]),E=ee.length>0&&ee.every(D=>M.has(D)),Ce=D=>{let $=D.every(ue=>M.has(ue)),fe=new Set(D);u?.($?[...M].filter(ue=>!fe.has(ue)):[...new Set([...M,...D])])},Xe=D=>N($=>{let fe=new Set($);return fe.has(D)?fe.delete(D):fe.add(D),fe}),X=(D,$)=>{let fe=D.node.key;if(!fe){Xe(D.node.id);return}u&&(p||$.shiftKey||$.ctrlKey||$.metaKey)?u(Zp([...M],fe,T.current??i,G,{range:$.shiftKey,additive:$.ctrlKey||$.metaKey,toggle:p&&!$.shiftKey})):r(fe),$.shiftKey||(T.current=fe)},Ee=D=>{let $=new Set(D.objectIds);return Object.keys(e).filter(fe=>!e[fe].removed&&$.has(e[fe].modelObjectId??fe))},Ze=Tt(lt().tier,"selectionSets",h.length),O=()=>{let D=[...M].filter($=>e[$]&&!e[$].removed);!D.length||!A.trim()||h.length>=128||!Ze||(m?.([...h,{id:crypto.randomUUID(),name:A.trim(),objectIds:D.map($=>e[$].modelObjectId??$)}]),K(""))};return gt("section",{className:`bb-nodeList ${n?"bb-nodeList--fill":""}`,children:[gt("div",{className:"bb-outlinerHead",children:[be("div",{className:"bb-search",children:be("input",{className:"bb-input","aria-label":"Filter objects",placeholder:"Filter objects",value:d,onChange:D=>x(D.target.value)})}),C&&be("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:be(px,{size:14})}),be("button",{type:"button",className:"bb-treeIcon","aria-label":"Expand all",title:"Expand all",onClick:()=>N(new Set),children:be(ax,{size:14})}),be("button",{type:"button",className:"bb-treeIcon","aria-label":"Collapse all",title:"Collapse all",onClick:()=>N(new Set(Xa(z,new Set,!0).filter(({node:D})=>D.children.length).map(({node:D})=>D.id))),children:be(rx,{size:14})})]}),u&&d.trim()&&ee.length>0&&gt("div",{className:"bb-selectionModeBar bb-selectionModeBar--matches",children:[gt("span",{children:[ee.length," ",ee.length===1?"match":"matches"]}),be("button",{type:"button",className:"bb-button bb-button--small",onClick:()=>Ce(ee),children:E?"Clear":"Select all"})]}),be(hx,{rows:Q,revealKey:i,bindings:e,selected:M,multiSelect:p,collapsed:b,searching:!!d.trim(),search:d,onSelect:X,onToggle:Xe,onToggleKeys:u?Ce:void 0,onSelectAll:u?()=>u(ee):void 0,onHover:t,isolatedItem:c,onIsolate:s,onRename:B,onSetVisible:w,onDelete:P,onFocus:v,onSetMultiSelected:u}),m&&gt("details",{className:"bb-selectionSets",children:[gt("summary",{children:["Saved selections",h.length?` (${h.length})`:""]}),gt("div",{className:"bb-selectionSetCreate",children:[be("input",{className:"bb-input","aria-label":"Selection name",placeholder:"Name this selection",maxLength:200,value:A,onChange:D=>K(D.target.value),onKeyDown:D=>{D.key==="Enter"&&(D.preventDefault(),O())}}),be("button",{type:"button",className:"bb-button bb-button--ghost",disabled:!M.size||!A.trim()||h.length>=128||!Ze,title:Ze?void 0:"Saving more selections requires the Starter plan or higher.",onClick:O,children:"Save"})]}),!h.length&&be("p",{children:"Select objects, then save the selection to reuse it."}),h.map(D=>{let $=Ee(D);return gt("div",{className:"bb-selectionSetRow",children:[gt("button",{type:"button",className:"bb-button bb-button--ghost",disabled:!$.length,title:$.length<D.objectIds.length?`${D.objectIds.length-$.length} objects unavailable`:void 0,onClick:()=>{x(""),N(new Set),u?.($),T.current=$[0]??null},children:[D.name,gt("small",{children:[$.length," / ",D.objectIds.length]})]}),be("button",{type:"button",className:"bb-treeIcon","aria-label":`Delete selection ${D.name}`,onClick:()=>m(h.filter(fe=>fe.id!==D.id)),children:be(ux,{size:14})})]},D.id)})]})]})}function hx({rows:e,revealKey:o,bindings:i,selected:r,multiSelect:t,collapsed:n,searching:c,search:s,onSelect:p,onToggle:f,onToggleKeys:u,onSelectAll:h,onHover:m,isolatedItem:C,onIsolate:B,onRename:w,onSetVisible:P,onDelete:v,onFocus:d,onSetMultiSelected:x}){let[b,N]=an(null),A=ex(()=>N(null),[]),K=hi(null),T=(O,D,$)=>{let fe=Vp(O.node,r,i);fe.length&&(K.current?.focus({preventScroll:!0}),O.node.key&&!r.has(O.node.key)&&x?.([O.node.key]),m?.(null),N({row:O,x:D,y:$,keys:fe}))};Qa(()=>{A()},[s,i,A]);let[z,y]=an(400),[Q,G]=an(0),[ee,le]=an(0),M=tx();es(()=>{let O=K.current;if(!O)return;let D=new ResizeObserver(()=>y(O.clientHeight));return D.observe(O),()=>D.disconnect()},[]),Qa(()=>{K.current&&(K.current.scrollTop=0),G(0),le(0)},[s]);let E=O=>{O=Math.max(0,Math.min(e.length-1,O)),le(O);let D=K.current;D&&(O*fo<D.scrollTop?D.scrollTop=O*fo:(O+1)*fo>D.scrollTop+D.clientHeight&&(D.scrollTop=(O+1)*fo-D.clientHeight))},Ce=hi(null);es(()=>{if(Ce.current===o)return;if(!o){Ce.current=null;return}let O=e.findIndex(({node:D})=>D.key===o);O<0||(Ce.current=o,E(O))});let Xe=O=>{let D=e[Math.min(ee,e.length-1)];if(D){if(O.key==="ContextMenu"||O.shiftKey&&O.key==="F10"){O.preventDefault(),O.stopPropagation();let $=document.getElementById(`${M}-${Math.min(ee,e.length-1)}`)?.getBoundingClientRect();$&&T(D,$.left+24,$.bottom);return}if((O.ctrlKey||O.metaKey)&&O.key.toLowerCase()==="a"){O.preventDefault(),O.stopPropagation(),h?.();return}if(["ArrowDown","ArrowUp","ArrowLeft","ArrowRight","Home","End","Enter"," "].includes(O.key)){if(O.preventDefault(),O.stopPropagation(),O.key==="ArrowDown"&&E(ee+1),O.key==="ArrowUp"&&E(ee-1),O.key==="Home"&&E(0),O.key==="End"&&E(e.length-1),O.key==="ArrowRight"&&D.node.children.length&&(n.has(D.node.id)?f(D.node.id):E(ee+1)),O.key==="ArrowLeft")if(D.node.children.length&&!n.has(D.node.id))f(D.node.id);else{let $=e.findIndex(fe=>fe.node.id===D.parentId);$>=0&&E($)}(O.key==="Enter"||O.key===" ")&&(O.key===" "&&t&&!D.node.key?u?.(D.node.keys):p(D,O))}}},X=Math.max(0,Math.min(e.length-1,Math.floor(Q/fo))-5),Ee=Math.min(e.length,X+Math.ceil(z/fo)+12),Ze=Math.min(ee,e.length-1);return gt(xx,{children:[gt("div",{ref:K,className:"bb-sceneTree",role:"tree","aria-label":"Scene hierarchy","aria-multiselectable":!!h,tabIndex:0,"aria-activedescendant":Ze>=X&&Ze<Ee?`${M}-${Ze}`:void 0,onKeyDown:Xe,onScroll:O=>{G(O.currentTarget.scrollTop),A()},children:[!e.length&&be("p",{className:"bb-treeEmpty",children:"No matching objects."}),be("div",{style:{height:e.length*fo,position:"relative"},children:e.slice(X,Ee).map((O,D)=>{let{node:$,depth:fe}=O,ue=X+D,mt=$.key?i[$.key]:void 0,Be=$.keys.reduce((Kt,ki)=>Kt+Number(r.has(ki)),0),eo=$.children.length?c||!n.has($.id):void 0,Vn=$.key?r.has($.key):Be===$.keys.length;return gt("div",{id:`${M}-${ue}`,role:"treeitem","aria-level":fe+1,"aria-expanded":eo,"aria-selected":Vn,className:`bb-treeRow${Vn?" bb-treeRow--selected":""}${$.key?" bb-treeRow--object":""}${mt?.visible===!1?" bb-treeRow--hidden":""}`,style:{top:ue*fo,height:fo,paddingLeft:4+Math.min(fe,10)*12},onContextMenu:Kt=>{Kt.preventDefault(),Kt.stopPropagation(),le(ue),T(O,Kt.clientX,Kt.clientY)},onFocus:()=>le(ue),onMouseEnter:()=>m?.($.key??null),onMouseLeave:()=>m?.(null),children:[$.children.length?be("button",{type:"button",tabIndex:-1,className:"bb-treeIcon","aria-label":`${eo?"Collapse":"Expand"} ${$.name}`,onClick:()=>f($.id),children:eo?be(nx,{size:13}):be(ix,{size:13})}):be("span",{className:"bb-treeSpacer"}),t&&u&&be(fx,{count:Be,total:$.keys.length,name:$.name,onChange:()=>u($.keys)}),gt("button",{type:"button",tabIndex:-1,className:"bb-treeNode",onClick:Kt=>{le(ue),K.current?.focus({preventScroll:!0}),p(O,Kt)},children:[mt?mt.type==="light"?be(cx,{size:13,"aria-hidden":"true"}):be(ox,{size:13,"aria-hidden":"true"}):be(dx,{size:13,"aria-hidden":"true"}),be("span",{title:mt?`${mt.type??"other"} \xB7 ${mt.modelObjectId}`:void 0,children:mt?.label||$.name}),mt?null:be("small",{children:$.keys.length})]}),mt?.visible===!1&&be(sx,{size:12,className:"bb-treeHiddenIcon","aria-label":"Hidden"}),$.key&&B&&be("button",{type:"button",tabIndex:-1,className:"bb-treeIcon bb-treeIsolate","aria-label":`${C===$.key?"Show all":"Isolate"} ${$.name}`,"aria-pressed":C===$.key,onClick:()=>B(C===$.key?null:$.key),children:be(lx,{size:13})})]},$.id)})})]}),b&&be(Yp,{x:b.x,y:b.y,name:b.row.node.key&&i[b.row.node.key]?.label||b.row.node.name,objectKey:b.row.node.key,objectId:b.row.node.key?i[b.row.node.key]?.modelObjectId??b.row.node.key:void 0,keys:b.keys,hidden:b.keys.every(O=>i[O]?.visible===!1),isolated:C===b.row.node.key,expanded:!c&&b.row.node.children.length?!n.has(b.row.node.id):void 0,onRename:w,onSetVisible:P,onDelete:v,onFocus:d,onIsolate:B,onSelectContents:x,onToggle:()=>f(b.row.node.id),onClose:A})]})}import{Fragment as Sx,jsx as sn,jsxs as ts}from"react/jsx-runtime";var os=[],Qp=vx(yx);function ns(e){let o=0;for(let i of Object.values(e))i.removed||(o+=1);return o}function yx({bindings:e,selectedItem:o,onSelect:i,onHover:r,modelGroups:t,onSelectModel:n,isolatedItem:c=null,onIsolate:s,multiSelectEnabled:p=!1,onToggleMultiSelect:f,onExitMultiSelect:u,multiSelectedKeys:h=os,onSetMultiSelected:m,hierarchy:C,selectionSets:B,onSelectionSetsChange:w,onRename:P,onSetVisible:v,onDelete:d,onFocus:x}){let b=t&&t.length>=2?t:null,N=b?b.reduce((A,K)=>A+ns(K.bindings),0):ns(e);return ts(Sx,{children:[p&&ts("div",{className:"bb-selectionModeBar",children:[ts("span",{children:[h.length," of ",N," selected"]}),sn("button",{type:"button",className:"bb-button bb-button--small","aria-label":"Exit multi-select",onClick:u??f,children:"Done"})]}),b?sn(wx,{groups:b,selectedItem:o,onSelect:i,onHover:r,onSelectModel:n,isolatedItem:c,onIsolate:s,multiSelectEnabled:p,multiSelectedKeys:h,onSetMultiSelected:m,onToggleMultiSelect:f,hierarchy:C,selectionSets:B,onSelectionSetsChange:w,onRename:P,onSetVisible:v,onDelete:d,onFocus:x}):sn(kr,{bindings:e,selectedItem:o,onSelect:i,onHover:r,isolatedItem:c,onIsolate:s,multiSelectEnabled:p,multiSelectedKeys:h,onSetMultiSelected:m,onToggleMultiSelect:f,hierarchy:C,selectionSets:B,onSelectionSetsChange:w,onRename:P,onSetVisible:v,onDelete:d,onFocus:x})]})}function wx({groups:e,selectedItem:o,onSelect:i,onHover:r,onSelectModel:t,isolatedItem:n=null,onIsolate:c,multiSelectEnabled:s=!1,multiSelectedKeys:p=os,onSetMultiSelected:f,onToggleMultiSelect:u,hierarchy:h,selectionSets:m,onSelectionSetsChange:C,onRename:B,onSetVisible:w,onDelete:P,onFocus:v}){return sn("section",{className:"bb-nodeList bb-nodeList--grouped",children:e.map(d=>{let x=d.isActive,b=ns(d.bindings),N=`${d.label} (${b})${d.isActive?" \xB7 Active":""}`,A=x;return sn("div",{className:`bb-groupItem ${A?"bb-groupItem--fill":""}`,children:sn(Je,{title:N,open:x,onToggle:()=>{t?.(d.url)},children:sn(kr,{bindings:d.bindings,hierarchy:d.isActive?h:void 0,selectionSets:d.isActive?m:void 0,onSelectionSetsChange:d.isActive?C:void 0,selectedItem:o,onSelect:K=>{t?.(d.url),i(K)},onHover:r,fill:A,isolatedItem:d.isActive?n:null,onIsolate:d.isActive?c:void 0,multiSelectEnabled:d.isActive&&s,multiSelectedKeys:d.isActive?p:os,onSetMultiSelected:d.isActive?f:void 0,onToggleMultiSelect:d.isActive?u:void 0,onRename:d.isActive?B:void 0,onSetVisible:d.isActive?w:void 0,onDelete:d.isActive?P:void 0,onFocus:d.isActive?v:void 0})})},d.url)})})}import{jsx as is,jsxs as kx}from"react/jsx-runtime";function rs({title:e,label:o,open:i,onToggle:r,draft:t,error:n,example:c,onDraftChange:s,onCommit:p}){return is(Je,{title:e,open:i,onToggle:r,children:kx("div",{className:"rui-stack",children:[is("textarea",{className:"bb-textarea","aria-label":o,placeholder:c,value:t,onChange:f=>s(f.target.value),onBlur:p}),n?is("span",{className:"bb-note bb-note--error",children:n}):null]})})}import{useCallback as At}from"react";import{PropertyBinding as ou}from"three";import{PropertyBinding as as}from"three";function eu(e){let o=new Map;return e.map(i=>{let r=(o.get(i)??0)+1;return o.set(i,r),r===1?i:`${i} (${r})`})}function ln(e,o,i=[],r={},t=new Set(Object.keys(Xi(e).nodesById))){let n=new Map(Object.entries(o).filter(([,m])=>m.removed===!0).map(([m,C])=>[C.modelObjectId??m,C])),c=new Set(Object.entries(r).map(([m,C])=>C.modelObjectId??m)),s=i.filter(m=>m.loadState==="loading").map(m=>as.sanitizeNodeName(`${Qt(m.namePrefix)}_`)),p=Object.fromEntries(Object.entries(o).filter(([m,C])=>{let B=C.modelObjectId??m;return!c.has(B)&&(C.removed===!0||t.has(B)||s.some(w=>B.startsWith(w)))})),f=Object.fromEntries(Object.entries(r).map(([m,C])=>[m,n.get(C.modelObjectId??m)??C])),u={...p,...f},h=Object.keys(u);return h.length===Object.keys(o).length&&h.every(m=>u[m]===o[m])?o:u}function Qt(e){return e.replace(/\.[^./\\]+$/,"")}function ss(e,o,i={}){let r=as.sanitizeNodeName(Qt(e)).replace(/_/g,"-")||"Model",t=o.map(s=>as.sanitizeNodeName(Qt(s.namePrefix))),n=Object.entries(i).map(([s,p])=>p.modelObjectId??s),c=r;for(let s=2;;s++){let p=`${c}_`;if(!t.some(f=>f===c||f.startsWith(p))&&!n.some(f=>f.startsWith(p)))return c;c=`${r}-${s}`}}function Un(e){e.resolved.cleanup()}function xi(e){e.resolved?.cleanup(),e.mergedModelSources.forEach(Un)}function vi(e,o){let i=gd(e),r=ni(i,ar(e));if(o){let n=new Map(Object.values(o).map(c=>[c.modelObjectId,c]));for(let c of i){let s=n.get(c);s&&(r[c]=s)}}e.updateMatrixWorld(!0);let t={};for(let n of i){let c=ei(e,n);if(!c){t[n]={position:[0,0,0],rotation:[0,0,0],scale:[1,1,1],pivotLocal:[0,0,0],rotationOrder:"XYZ"};continue}let s=ad(c);t[n]={position:[c.position.x,c.position.y,c.position.z],rotation:[c.rotation.x,c.rotation.y,c.rotation.z],scale:[c.scale.x,c.scale.y,c.scale.z],pivotLocal:[s.x,s.y,s.z],rotationOrder:c.rotation.order}}return{bindings:r,originalTransforms:t,nodeNames:i}}function Cx(e,o){let i=e;for(;i;){if(i===o)return!0;i=i.parent}return!1}function ls(e,o){let i=e.parent??e,r=vi(i,o),t=r.nodeNames.filter(n=>{let c=ei(i,n);return c?Cx(c,e):!1});return{bindings:Object.fromEntries(t.map(n=>[n,r.bindings[n]])),originalTransforms:Object.fromEntries(t.map(n=>[n,r.originalTransforms[n]])),nodeNames:t}}function Cr(e,o=[]){let i={bindings:e,mergeSources:o};return{past:[],present:i,future:[],baseline:i,edits:0}}function nu(e,o){let i=o(e.present),r=e.past.map(o),t=e.future.map(o),n=o(e.baseline);return i===e.present&&n===e.baseline&&r.every((c,s)=>c===e.past[s])&&t.every((c,s)=>c===e.future[s])?e:{...e,present:i,past:r,future:t,baseline:n}}function iu(e,o,i,r={}){return nu(e,t=>{if(!t.mergeSources.some(s=>s.url===o))return t;let n=new Map(Object.entries(t.bindings).map(([s,p])=>[p.modelObjectId??s,p])),c={...t.bindings};for(let[s,p]of Object.entries(r))c[s]=n.get(p.modelObjectId??s)??p;return{bindings:c,mergeSources:t.mergeSources.map(s=>s.url===o?{...s,...i}:s)}})}function ds(e,o){let i=e.mergeSources.find(n=>n.url===o);if(!i)return e;let r=new Set(i.nodeNames),t=ou.sanitizeNodeName(`${Qt(i.namePrefix)}_`);return{mergeSources:e.mergeSources.filter(n=>n.url!==o),bindings:Object.fromEntries(Object.entries(e.bindings).filter(([n,c])=>{let s=c.modelObjectId??n;return!r.has(s)&&!r.has(n)&&!s.startsWith(t)}))}}function cs(e,o){let i=bo(e.bindingHistory??Cr(e.bindings,e.mergedModelSources),{type:"set",updater:o,track:!0,coalesce:!1});return{...e,bindings:i.present.bindings,mergedModelSources:i.present.mergeSources,bindingHistory:i}}function ps(e,o,i,r){let t=iu(e.bindingHistory??Cr(e.bindings,e.mergedModelSources),o,i,r);return{...e,bindings:t.present.bindings,mergedModelSources:t.present.mergeSources,bindingHistory:t}}function ru(e,o){let i=e.bindingHistory??Cr(e.bindings,e.mergedModelSources),t=[i.present,...i.past,...i.future].flatMap(s=>s.mergeSources).map(s=>ou.sanitizeNodeName(`${Qt(s.namePrefix)}_`)),n=Object.fromEntries(Object.entries(o).filter(([s,p])=>!t.some(f=>(p.modelObjectId??s).startsWith(f)))),c=nu(i,s=>({...s,bindings:{...n,...s.bindings}}));return{...e,bindings:c.present.bindings,bindingHistory:c}}function tu(e,o){let i=new Set(o.mergeSources.map(r=>r.url));return{...e,present:{...e.present,mergeSources:e.present.mergeSources.map(r=>i.has(r.url)?r:{...r,loadState:"loading"})}}}function au(e,o=[]){let i=di({bindings:e,mergeSources:o}),{setValue:r,setValueAsStep:t,updateHistory:n,restoreSnapshot:c}=i,s=At(x=>r(b=>{let N=typeof x=="function"?x(b.bindings):x;return N===b.bindings?b:{...b,bindings:N}}),[r]),p=At(x=>t(b=>{let N=typeof x=="function"?x(b.bindings):x;return N===b.bindings?b:{...b,bindings:N}}),[t]),f=At(x=>n(b=>{let N=typeof x=="function"?x(b.present.bindings):x;if(N===b.present.bindings)return b;let A={...b.present,bindings:N};return{...b,present:A,baseline:b.edits===0?A:b.baseline}}),[n]),u=At(x=>n(b=>{let N=typeof x=="function"?x(b.present.mergeSources):x,A={...b.present,mergeSources:N};return{...b,present:A,baseline:b.edits===0?A:b.baseline}}),[n]),h=At(x=>t(b=>({...b,mergeSources:[...b.mergeSources,typeof x=="function"?x(b):x]})),[t]),m=At(x=>t(b=>ds(b,x)),[t]),C=At((x,b,N)=>{n(A=>iu(A,x,b,N))},[n]),B=At(()=>c(x=>{let b=bo(x,{type:"undo"});return b===x?x:tu(b,x.present)}),[c]),w=At(()=>c(x=>{let b=bo(x,{type:"redo"});return b===x?x:tu(b,x.present)}),[c]),P=At((x,b)=>c(N=>bo(N,{type:"reset",value:{bindings:x,mergeSources:N.present.mergeSources},track:b?.asEdit??!1})),[c]),v=At(()=>c(x=>bo(x,{type:"reset",value:x.present,track:!1})),[c]),d=At(x=>c({...x.bindingHistory??Cr(x.bindings,x.mergedModelSources),present:{bindings:x.bindings,mergeSources:x.mergedModelSources}}),[c]);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:f,setMergeSourcesUntracked:u,addMerge:h,removeMerge:m,hydrateMerge:C,undo:B,redo:w,reset:P,clearHistory:v,restoreModel:d}}import{useEffect as su,useRef as Mx}from"react";function lu(e,o,{modelUrl:i,modelSourceRef:r,uploadedFilesRef:t}={}){let n=Mx(new Map);su(()=>{let c=new Map,s=u=>{for(let h of[u.present,...u.past,...u.future])h.mergeSources.forEach(m=>c.set(m.url,m))};s(e);for(let u of o)u.bindingHistory&&s(u.bindingHistory),u.mergedModelSources.forEach(h=>c.set(h.url,h));for(let[u,h]of n.current)c.has(u)||h.resolved.cleanup();n.current=c;let p=new Set,f=u=>{u?.kind==="file"&&p.add(u.key)};i&&f(r?.current?.model),o.forEach(u=>f(u.sessionModel)),c.forEach(u=>f(u.sessionModel));for(let u of t?.current.keys()??[])p.has(u)||t?.current.delete(u)},[e,o,i,r,t]),su(()=>()=>{n.current.forEach(c=>c.resolved.cleanup()),n.current.clear(),t?.current.clear()},[t])}import{useCallback as Px,useEffect as us,useRef as Bx}from"react";var Tx=500;function du({composition:e,autosaveEnabled:o,hasEdits:i,modelUrl:r,bindings:t,sceneConfig:n,parkedModels:c,mergedModelSources:s,modelOrder:p,onTextureUpload:f,modelSourceRef:u,pendingLoadRef:h,storedModelKeysRef:m,uploadedFilesRef:C,pendingAutosaveRef:B,autosaveFailureShownRef:w,setStatusMessage:P,setStatusTone:v}){let d=Bx(0),x=Px(async(b,N)=>{if(f)return f(b,N);let A=URL.createObjectURL(b);if(o)try{await An(A,b)}catch(K){console.warn("[BindingBuilder] Could not store texture file for autosave:",K)}return A},[f,o]);return us(()=>{if(!o||!i){B.current=null;return}let b=u.current;if(r&&!b){B.current=null;return}let N=r,A=()=>{if(B.current!==A||h.current)return;B.current=null;let T=++d.current,z=X=>{console.warn("[BindingBuilder] Autosave failed:",X),!w.current&&(w.current=!0,P("Couldn't autosave this session \u2014 the browser refused to store it, possibly for lack of space. Export your work to keep it."),v("error"))};if(!N||!b){m.current.clear(),Yd().then(()=>{T===d.current&&(w.current=!1)}).catch(z);return}let{model:y}=b,Q=[],G=new Set,ee=X=>{if(!X||X.kind!=="file"||(G.add(X.key),m.current.has(X.key)))return;let Ee=C.current.get(X.key);Ee&&Q.push({key:X.key,file:Ee})};ee(y),c.forEach(X=>{ee(X.sessionModel),X.mergedModelSources.forEach(Ee=>ee(Ee.sessionModel))}),s.forEach(X=>ee(X.sessionModel)),m.current=new Set([...m.current].filter(X=>G.has(X)));let le=X=>({model:X.sessionModel,namePrefix:X.namePrefix}),M=c.filter(X=>!!X.sessionModel).map(X=>({model:X.sessionModel,bindings:X.bindings,originalTransforms:X.originalTransforms,modelSettings:X.modelSettings,mergeModels:X.mergedModelSources.map(le)})),E=s.map(le),Ce=new Map;Ce.set(N,y),c.forEach(X=>{X.sessionModel&&Ce.set(X.url,X.sessionModel)});let Xe=p.map(X=>{let Ee=Ce.get(X);return Ee?Yt(Ee):null}).filter(X=>X!==null);qd({model:y,composition:e,bindings:t,sceneConfig:n,parkedModels:M,mergeModels:E,modelOrder:Xe},Q).then(()=>{T===d.current&&(m.current=G,w.current=!1)}).catch(z)};if(B.current=A,!N){A();return}let K=window.setTimeout(A,Tx);return()=>window.clearTimeout(K)},[e,o,i,r,t,n,c,s,p]),us(()=>{if(!o)return;let b=()=>B.current?.(),N=()=>{document.visibilityState==="hidden"&&b()};return window.addEventListener("pagehide",b),document.addEventListener("visibilitychange",N),()=>{window.removeEventListener("pagehide",b),document.removeEventListener("visibilitychange",N),b()}},[o]),us(()=>{if(!o||!r||!i)return;let b=N=>{B.current?.(),N.preventDefault(),N.returnValue=""};return window.addEventListener("beforeunload",b),()=>window.removeEventListener("beforeunload",b)},[o,r,i]),{handleTextureUpload:x}}import{useCallback as bs,useEffect as Rx,useRef as dn}from"react";var gs=640,ms=360,Nx=.82,Ax=4e3,Ox=2*6e4,cu=1e3,Ex=6e4;function jx({now:e,lastActivityAt:o,lastCaptureAt:i,ready:r,loadingTiles:t}){if(!r)return cu;let n=e-o;return t&&n<Ex?cu:Math.max(Ax-n,Ox-(e-i),0)}async function Ix(e){let o=new Image;o.src=e,await o.decode();let i=document.createElement("canvas");i.width=gs,i.height=ms;let r=Math.max(gs/o.naturalWidth,ms/o.naturalHeight),t=o.naturalWidth*r,n=o.naturalHeight*r,c=i.getContext("2d");if(!c)throw new Error("No 2D canvas to draw the thumbnail on.");return c.imageSmoothingQuality="high",c.drawImage(o,(gs-t)/2,(ms-n)/2,t,n),new Promise((s,p)=>{i.toBlob(f=>f?s(f):p(new Error("Could not encode the thumbnail.")),"image/jpeg",Nx)})}function pu({onCapture:e,hasThumbnail:o,viewerRef:i,isModelLoading:r}){let t=dn(e);t.current=e;let n=dn(r);n.current=r;let c=dn(!1),s=dn(!1),p=dn(null),f=dn(0),u=dn(Number.NEGATIVE_INFINITY),h=bs(()=>{if(!t.current||!c.current||s.current||p.current!==null)return;let w=i.current,P=Date.now(),v=jx({now:P,lastActivityAt:f.current,lastCaptureAt:u.current,ready:!!w&&!n.current()&&document.visibilityState==="visible",loadingTiles:w?.isLoadingTiles()??!1});if(v>0){p.current=window.setTimeout(()=>{p.current=null,h()},v);return}s.current=!0,c.current=!1,u.current=P,w.captureImage({type:"image/jpeg",quality:.92}).then(Ix).then(d=>t.current?.(d)).catch(d=>{c.current=!0,console.warn("[react-immersive] Could not update the project thumbnail.",d)}).finally(()=>{s.current=!1,h()})},[i]),m=bs(()=>{f.current=Date.now()},[]),C=bs(()=>{m(),c.current=!0,h()},[m,h]),B=!!e;return Rx(()=>{if(!B)return;f.current=Date.now(),o||(c.current=!0),h();let w=["pointermove","pointerdown","keydown","wheel"];for(let P of w)window.addEventListener(P,m,{passive:!0,capture:!0});return()=>{for(let P of w)window.removeEventListener(P,m,{capture:!0});p.current!==null&&window.clearTimeout(p.current),p.current=null}},[B,o,m,h]),{markThumbnailOutdated:C,noteThumbnailActivity:m}}import{useLayoutEffect as zx}from"react";function uu({bindings:e,multiSelectMode:o,selectedItem:i,multiSelectedKeys:r,setSelectedItem:t,setMultiSelectedKeys:n}){zx(()=>{let c=p=>!!(e[p]&&!e[p].removed),s=r.filter(c);s.length!==r.length&&n(s),i&&(!c(i)||o&&!s.includes(i))&&t(o?s[s.length-1]??null:null)},[e,o,i,r,t,n])}import{useCallback as zo,useReducer as Dx}from"react";var hs={selectedItem:null,keys:[],checkboxMode:!1},fs=(e,o)=>typeof e=="function"?e(o):e;function Lx(e,o){if(o.type==="primary"){let p=fs(o.value,e.selectedItem);return p===e.selectedItem?e:{...e,selectedItem:p}}if(o.type==="keys"){let p=fs(o.value,e.keys);return p===e.keys?e:{...e,keys:p}}if(o.type==="mode"){let p=fs(o.value,e.checkboxMode);return p===e.checkboxMode?e:{...e,checkboxMode:p}}if(o.type==="clear")return hs;if(o.type==="exitMode"||o.type==="toggleMode"&&e.checkboxMode)return{...e,checkboxMode:!1,keys:[]};if(o.type==="toggleMode")return{...e,checkboxMode:!0,keys:e.keys.length?e.keys:e.selectedItem?[e.selectedItem]:[]};if(o.type==="selection"){let p=[...new Set(o.keys)];return{...e,keys:p,selectedItem:e.selectedItem&&p.includes(e.selectedItem)?e.selectedItem:p[p.length-1]??null}}if(o.type!=="select")return e;let{key:i,modifiers:r}=o;if(!i)return e.checkboxMode?e:hs;if(!e.checkboxMode&&!r.shiftKey&&!r.ctrlKey&&!r.metaKey)return{...e,selectedItem:i,keys:[]};let t=e.keys.length?e.keys:e.selectedItem?[e.selectedItem]:[],n=r.shiftKey&&!r.ctrlKey&&!r.metaKey,c=t.includes(i)&&!n,s=c?t.filter(p=>p!==i):[...new Set([...t,i])];return{...e,keys:s,selectedItem:c?e.selectedItem&&s.includes(e.selectedItem)?e.selectedItem:s[s.length-1]??null:i}}function bu(){let[e,o]=Dx(Lx,hs),i=zo(u=>o({type:"primary",value:u}),[]),r=zo(u=>o({type:"keys",value:u}),[]),t=zo(u=>o({type:"mode",value:u}),[]),n=zo(u=>o({type:"selection",keys:u}),[]),c=zo((u,h={})=>o({type:"select",key:u,modifiers:h}),[]),s=zo(()=>o({type:"toggleMode"}),[]),p=zo(()=>o({type:"exitMode"}),[]),f=zo(()=>o({type:"clear"}),[]);return{selectedItem:e.selectedItem,multiSelectedKeys:e.keys,multiSelectMode:e.checkboxMode,groupSelectionActive:e.checkboxMode||e.keys.length>1,setSelectedItem:i,setMultiSelectedKeys:r,setMultiSelectMode:t,setSelection:n,selectObject:c,toggleMultiSelect:s,exitMultiSelect:p,clearSelection:f}}import{useCallback as gu,useEffect as Fx,useState as Hx}from"react";function mu(e,o){let[i,r]=Hx(!1),t=e>0||o>0,n=gu(()=>r(!0),[]),c=gu(()=>r(!1),[]);return Fx(()=>{t&&n()},[t,n]),{hasEdits:i||t,markSessionEdited:n,resetSessionEdits:c}}import{useEffect as fu,useReducer as $x,useRef as hu}from"react";function xu({enabled:e=!0,modelUrl:o,bindings:i,mergeSources:r,parkedModels:t,scenesRef:n,sceneRevision:c,setBindings:s,setParkedModels:p}){let[f,u]=$x(C=>C+1,0),h=hu(new WeakMap),m=hu(new WeakMap);fu(()=>{if(!e)return;let C=[o,...t.map(P=>P.url)],B=new Set(C.flatMap(P=>{let v=P?n.current.get(P):void 0;return v?[v]:[]})),w=P=>{P.target&&h.current.delete(P.target),u()};for(let P of B)P.addEventListener("childadded",w),P.addEventListener("childremoved",w);return()=>{for(let P of B)P.removeEventListener("childadded",w),P.removeEventListener("childremoved",w)}},[e,o,t,n,c]),fu(()=>{if(!e)return;let C=P=>{let v=h.current.get(P);return v||(v=new Set(Object.keys(Xi(P).nodesById)),h.current.set(P,v)),v},B=(P,v)=>{let d=C(P),x=m.current.get(P)??new Set;m.current.set(P,x);for(let[b,N]of Object.entries(v))N.removed&&x.add(N.modelObjectId??b);for(let b of x)d.has(b)&&x.delete(b);return x.size?new Set([...d,...x]):d},w=o?n.current.get(o):void 0;if(w){let P=B(w,i);s(v=>ln(w,v,r,{},P))}p(P=>{let v=!1,d=P.map(x=>{let b=n.current.get(x.url);if(!b)return x;let N=ln(b,x.bindings,x.mergedModelSources,{},B(b,x.bindings));return N===x.bindings?x:(v=!0,{...x,bindings:N})});return v?d:P})},[e,o,i,r,t,n,c,f,s,p])}import{useEffect as Ux,useMemo as Vx,useReducer as _x}from"react";function vu({modelUrl:e,scenesRef:o,sceneRevision:i,streaming:r=!1}){let t=e?o.current.get(e):void 0,[n,c]=_x(s=>s+1,0);return Ux(()=>{if(!t||r)return;let s=()=>c();return t.addEventListener("childadded",s),t.addEventListener("childremoved",s),()=>{t.removeEventListener("childadded",s),t.removeEventListener("childremoved",s)}},[t,r]),Vx(()=>({materialVariantGroups:t?Xl(t):[],objectsWithoutUvs:t&&!r?ar(t):new Set,hierarchy:t&&!r?Nd(t):[]}),[t,i,n,r])}import{AlertTriangle as Kx,Box as Gx,History as qx,Trash2 as Wx,Upload as Yx}from"lucide-react";import{useId as yu,useState as Jx}from"react";import{Fragment as yi,jsx as ge,jsxs as Ve}from"react/jsx-runtime";function Xx(e){let o=new Date(e);return o.toDateString()===new Date().toDateString()?`today at ${o.toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}`:o.toLocaleString([],{dateStyle:"medium",timeStyle:"short"})}var xs=ge(Kx,{size:15,"aria-hidden":"true"});function _t({variant:e,...o}){return ge("button",{type:"button",className:`bb-dialogButton ${e?`bb-dialogButton--${e}`:""}`,...o})}function wu({target:e,onCancel:o,onConfirm:i}){return Ve(Rn,{title:`Reset ${e==="bindings"?"object changes":e==="assets"?"asset placements":"scene settings"}?`,icon:xs,onCancel:o,footer:Ve(yi,{children:[ge(_t,{onClick:o,children:"Cancel"}),ge(_t,{variant:"danger",onClick:i,autoFocus:!0,children:"Reset"})]}),children:[ge("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."}),ge("p",{children:e==="assets"?"You can undo this.":"You can't undo this."})]})}function Su({models:e,savedAt:o,onCancel:i,onConfirm:r}){return Ve(Rn,{title:"Restore last session",icon:ge(qx,{size:15,className:"bb-dialogIconNeutral","aria-hidden":"true"}),onCancel:i,footer:Ve(yi,{children:[ge(_t,{onClick:i,children:"Cancel"}),ge(_t,{variant:"primary",onClick:r,autoFocus:!0,children:"Restore"})]}),children:[Ve("p",{children:["Saved ",Xx(o),", with your bindings and scene settings."]}),ge("ul",{className:"bb-modelList","aria-label":"Saved models",children:e.map((t,n)=>Ve("li",{className:"bb-modelRow",children:[ge(Gx,{size:14,className:"bb-modelRowIcon","aria-hidden":"true"}),Ve("span",{className:"bb-modelRowText",children:[ge("span",{className:"bb-modelRowName",title:t.name,children:t.name}),t.mergedCount>0?Ve("small",{children:[t.mergedCount," merged ",t.mergedCount===1?"model":"models"]}):null]})]},n))})]})}function ku({nodeLabel:e,count:o=1,onCancel:i,onConfirm:r}){let t=o>1;return Ve(Rn,{title:t?`Delete ${e}?`:"Delete this object?",icon:xs,onCancel:i,footer:Ve(yi,{children:[ge(_t,{onClick:i,children:"Cancel"}),ge(_t,{variant:"danger",onClick:r,autoFocus:!0,children:"Delete"})]}),children:[t?null:ge("p",{children:ge("strong",{children:e})}),Ve("p",{children:[t?"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:o,onChoose:i}){let[r,t]=Jx(e.find(s=>s.isActive)?.url??e[0]?.url??""),n=e.find(s=>s.url===r),c=yu();return Ve(Rn,{title:"Add model",icon:ge(Yx,{size:15,"aria-hidden":"true"}),onCancel:o,footer:Ve(yi,{children:[ge(_t,{onClick:o,children:"Cancel"}),ge(_t,{onClick:()=>i({mode:"separate"}),children:"Add as separate model"}),ge(_t,{variant:"primary",disabled:!n,title:n?`Merge into ${n.name}`:void 0,onClick:()=>n&&i({mode:"merge",targetUrl:r}),children:"Merge into model"})]}),children:[ge("p",{children:"A separate model stays independent and has its own group in the Outliner. Merging adds its objects to the model you choose."}),ge("label",{htmlFor:c,children:"Merge into"}),ge("select",{id:c,value:r,onChange:s=>t(s.target.value),children:e.map(s=>Ve("option",{value:s.url,children:[s.label,": ",s.name,s.isActive?" (active)":""]},s.url))})]})}function Mu({options:e,onCancel:o,onRemoveModel:i,onRemoveMerge:r,onRemoveAll:t,permanent:n=!1}){let c=yu();return Ve(Rn,{title:"Remove model",icon:xs,onCancel:o,footer:Ve(yi,{children:[ge(_t,{onClick:o,children:"Cancel"}),t?ge(_t,{variant:"danger","aria-describedby":c,onClick:t,children:"Remove all models"}):null]}),children:[ge("p",{children:"Its bindings, transforms and anything merged into it go with it. The other models stay."}),ge("ul",{className:"bb-modelList","aria-label":"Models",children:e.map(s=>Ve("li",{className:"bb-modelRow",children:[Ve("span",{className:"bb-modelRowText",children:[ge("span",{className:"bb-modelRowName",title:s.label,children:s.label}),s.kind!=="model"?Ve("small",{children:["Merged into ",s.ownerLabel]}):s.name!==s.label?ge("small",{title:s.name,children:s.name}):null]}),s.kind==="model"&&s.isActive?ge("span",{className:"bb-modelRowBadge",children:"Active"}):null,Ve("button",{type:"button",className:"bb-removeRowButton","aria-label":`Remove ${s.label}`,onClick:()=>s.kind==="model"?i(s.url):r(s.url),children:[ge(Wx,{size:13,"aria-hidden":"true"}),"Remove"]})]},s.url))}),ge("p",{id:c,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 Zx}from"fflate";function Qx(e){return(e.decals??[]).map(o=>o.image).filter(o=>!!o?.trim())}function ev(e){let o=e.style?.material;return o?Object.values(o).filter(i=>!!i&&typeof i=="object"&&typeof i.path=="string"&&i.path.trim().length>0).map(i=>i.path):[]}async function Pu(e){let o=new Set;for(let i of Object.values(e)){for(let r of ev(i))o.add(r);for(let r of Qx(i))o.add(r)}return Tu(o)}async function Bu(e){let o=new Set,i=e.background?.imageUrl?.trim();return i&&o.add(i),Tu(o)}async function Tu(e){let o=[],i=[];return await Promise.all(Array.from(e).map(async r=>{let t=Wt(r);if(t)try{let n=await fetch(t);if(!n.ok)throw new Error(String(n.status));o.push({path:r,blob:await n.blob()});return}catch{i.push(r);return}try{let n=await po(r);n&&o.push({path:r,blob:n})}catch{}})),{assets:o,failedPaths:i}}async function wi(e,o,i,r,t){if(t.length===0){up(e,o,i);return}let n={[e]:Zx(o)};for(let s of t)n[s.path]=new Uint8Array(await s.blob.arrayBuffer());let c=await rr(n);Pn(new Blob([c],{type:"application/zip"}),r)}async function Mr(e){let o=e.background?.imageUrl?.trim();if(o)try{let i=await po(o);i&&Ht(o,URL.createObjectURL(i))}catch(i){console.warn("[BindingBuilder] Could not rehydrate the background image:",i)}}async function cn(e){return await Promise.all(Object.entries(e).map(async([o,i])=>{for(let t of i.decals??[])if(t.image)try{let n=await po(t.image);n&&Ht(t.image,URL.createObjectURL(n))}catch(n){console.warn(`[BindingBuilder] Could not rehydrate a decal image on "${o}":`,n)}let r=i.style?.material;if(r)for(let t of Ql){let c=r[t]?.path;if(c)try{let s=await po(c);if(!s){console.warn(`[BindingBuilder] No stored texture found for "${o}"'s ${t} ("${c}"). 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);Ht(c,p)}catch(s){console.warn(`[BindingBuilder] Could not rehydrate "${o}"'s ${t}:`,s)}}})),e}async function Si(e){if(!e)return;let o={};for(let i of e.definition.groups)for(let r of i.options)for(let[t,n]of(r.appearance??[]).entries())if(n.material){let c=JSON.stringify([i.id,r.id,t]);o[c]={id:c,modelObjectId:c,style:{material:n.material}}}await cn(o)}async function Ru(e){let o=new Set,i=new WeakSet;function r(t,n=0){if(!(!t||typeof t!="object"||i.has(t)||n>64)){i.add(t);for(let[c,s]of Object.entries(t))c!=="metadata"&&(c==="path"&&typeof s=="string"&&s?o.add(s):r(s,n+1))}}return r(e),await Promise.all([...o].map(async t=>{let n=await po(t);n&&Ht(t,URL.createObjectURL(n))})),e}function Nu({bindings:e,setBindings:o,sceneConfig:i,setSceneConfig:r,nodeKeys:t,sceneConfigInputRef:n,setIsExporting:c,setStatusMessage:s,setStatusTone:p}){let f=v=>h("bindings",()=>Pu(e),d=>v==="json"?wi("objectBindings.json",bi(e),"application/json","objectBindings.zip",d):wi("objectBindings.ts",xr(e),"text/typescript","objectBindings-ts.zip",d)),u=v=>h("scene config",()=>Bu(i),d=>v==="json"?wi("sceneConfig.json",vr(i),"application/json","sceneConfig.zip",d):wi("sceneConfig.ts",yr(i),"text/typescript","sceneConfig-ts.zip",d)),h=async(v,d,x)=>{c(!0);try{let{assets:b,failedPaths:N}=await d();await x(b),N.length>0?(s(`Exported, but ${N.length} uploaded image${N.length===1?"":"s"} couldn't be bundled: ${N.join(", ")}.`),p("error")):b.length>0&&(s(`Exported with ${b.length} uploaded image${b.length===1?"":"s"} bundled into the zip.`),p("success"))}catch(b){let N=b instanceof Error?b.message:"Unknown export error.";s(`Failed to export ${v}: ${N}`),p("error")}finally{c(!1)}},m=async v=>{if(!t.length){s("Load a model before importing bindings."),p("error");return}let d;try{d=JSON.parse(await v.text())}catch{s(`${v.name} is not valid JSON.`),p("error");return}if(d===null||typeof d!="object"||Array.isArray(d)){s("Expected a JSON object mapping object IDs to bindings."),p("error");return}let x=new Map;for(let z of Object.values(d))if(z!==null&&typeof z=="object"&&typeof z.id=="string"&&typeof z.type=="string"&&typeof z.modelObjectId=="string"){let y=z;x.set(y.modelObjectId,y)}if(x.size===0){s(`${v.name} doesn't look like an exported bindings file.`),p("error");return}let b={...e},N={},A=0;for(let z of Object.keys(b)){let y=x.get(z);y&&(b[z]=y,N[z]=y,A++)}if(A===0){s(`None of the object IDs in ${v.name} match this model \u2014 nothing imported.`),p("error");return}let K=await cn(N);Object.assign(b,K),o(b);let T=x.size-A;s(T>0?`Imported ${A} binding${A===1?"":"s"} from ${v.name} (${T} skipped \u2014 not in this model).`:`Imported ${A} binding${A===1?"":"s"} from ${v.name}.`),p("success")},C=async v=>{let d=v.target.files?.[0];d&&(await m(d),v.target.value="")},B=()=>{n.current?.click()},w=async v=>{let d;try{d=JSON.parse(await v.text())}catch{s(`${v.name} is not valid JSON.`),p("error");return}if(d===null||typeof d!="object"||Array.isArray(d)){s("Expected a JSON object with scene config sections."),p("error");return}let x=["model","camera","lighting","wireframe","shadows","environment","background","groundShadows","postProcessing","animations","annotations","cinematic","styleRules","section","measurements","selectionSets","product"],b=d;if(b.product!==void 0)try{b.product=tr(b.product)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(b.section!==void 0)try{b.section=Qi(i.section,b.section)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(b.selectionSets!==void 0)try{b.selectionSets=Mn(b.selectionSets)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}if(b.measurements!==void 0)try{b.measurements=er(b.measurements)}catch(A){s(A instanceof Error?A.message:String(A)),p("error");return}let N=x.filter(A=>b[A]!==void 0);if(N.length===0){s(`${v.name} doesn't look like an exported scene config file.`),p("error");return}await Si(b.product),N.includes("background")&&b.background&&await Mr({background:b.background}),r(A=>{let K={...A};for(let T of N)K[T]=T==="measurements"||T==="section"||T==="product"?b[T]:li(A[T],b[T]);return K}),s(`Imported ${N.length} section${N.length===1?"":"s"} from ${v.name}.`),p("success")};return{handleExportBindings:f,handleExportSceneConfig:u,importBindingsFile:m,handleImportBindingsChange:C,openSceneConfigImportPicker:B,importSceneConfigFile:w,handleImportSceneConfigChange:async v=>{let d=v.target.files?.[0];d&&(await w(d),v.target.value="")}}}var vs={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"]},Au=Object.keys(vs);function Ou(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 o=e.path;return typeof o=="string"&&o.trim().length>0}return!1}function ys(e){if(e)return Object.values(e).some(Ou)?e:void 0}function Ot(e,o){return e?vs[o].some(i=>Ou(e[i])):!1}function ws(e){return{pbr:Ot(e,"pbr"),roughness:Ot(e,"roughness"),emission:Ot(e,"emission"),opacity:Ot(e,"opacity"),normalBump:Ot(e,"normalBump"),displacement:Ot(e,"displacement"),ao:Ot(e,"ao"),clearcoat:Ot(e,"clearcoat"),sheen:Ot(e,"sheen"),anisotropy:Ot(e,"anisotropy"),transmission:Ot(e,"transmission"),faces:Ot(e,"faces")}}function Ss(e,o){if(o)return{...e,style:{...e.style,material:o}};if(!e.style)return e;let{material:i,...r}=e.style;return{...e,style:Object.keys(r).length>0?r:void 0}}function Eu(e,o){if(!e)return;let i={...e};for(let r of vs[o])delete i[r];return i}import{ChevronDown as tv,ChevronUp as ov}from"lucide-react";import{jsx as pn,jsxs as ju}from"react/jsx-runtime";function Iu({panel:e,tabs:o,tab:i,onTabChange:r,hasModel:t,onPointerDownCapture:n,children:c}){let s=e.open&&t;return ju("div",{className:`bb-dock ${s?"bb-dock--open":""}`,onPointerDownCapture:n,children:[s?pn(ui,{orientation:"horizontal",label:"Resize timeline",onPointerDown:e.startResize,onKeyDown:e.onResizeKey}):null,ju("div",{className:"bb-tabs bb-dockBar",role:"tablist","aria-label":"Animation",children:[o.map(({id:p,label:f})=>pn("button",{type:"button",role:"tab",disabled:!t,"aria-selected":e.open&&i===p,className:`bb-tab ${e.open&&i===p?"bb-tab--active":""}`,onClick:()=>{e.open&&i===p?e.setOpen(!1):(r(p),e.setOpen(!0))},children:f},p)),pn("span",{className:"bb-topBarSpacer"}),pn("button",{type:"button",className:"bb-toolButton bb-toolButton--small",disabled:!t,"aria-label":e.open?"Collapse timeline":"Expand timeline",onClick:()=>e.setOpen(!e.open),children:e.open?pn(tv,{size:14}):pn(ov,{size:14})})]}),s?pn("div",{className:"bb-dockBody",style:{height:e.size},children:c}):null]})}import{Fragment as it,jsx as R,jsxs as se}from"react/jsx-runtime";var hv=Oo(()=>import("./AnnotationsTab-OHRVWRKI.mjs")),xv=Oo(()=>import("./AnimationsTab-NUJTEMZ5.mjs")),vv=Oo(()=>import("./SequencesTab-VZKEKAUG.mjs")),yv=Oo(()=>import("./CinematicTab-IJAY2BS6.mjs")),wv=Oo(()=>import("./ConfigureTab-UQRRATCY.mjs")),Du="/room.glb";function ks(){return`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function Cs(e){return`Couldn't reload ${e} from your last session. It's still saved in this browser.`}function Sv({label:e,values:o,onChange:i}){let r=o.length>0&&o.every(Boolean),t=!r&&o.some(Boolean);return se("label",{className:"bb-groupFlag",children:[R("input",{type:"checkbox",ref:n=>{n&&(n.indeterminate=t)},checked:r,onChange:n=>i(n.target.checked)}),e]})}var kv=[{id:"outliner",label:"Outliner"},{id:"assets",label:"Assets"},{id:"annotations",label:"Annotations"},{id:"measure",label:"Measure"}],Cv=[{id:"sequences",label:"Sequences"},{id:"clips",label:"Clips"},{id:"cinematic",label:"Cinematic"}],Lu=[{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}],Fu={bindings:"object",scene:"scene",assets:"asset"},Mv=se(it,{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 Hu(e,o=!1){let i=e;return i?.tagName?i.isContentEditable||i.tagName==="TEXTAREA"||o&&i.tagName==="SELECT"?!0:i.tagName!=="INPUT"?!1:!["range","checkbox","radio","button","file","color"].includes(i.type):!1}function Pv({topBarStart:e,configurePublish:o,licenseKey:i,licenseValidationUrl:r,onLicenseStatusChange:t,arHandoff:n=!0,mobileHandoffUrl:c,dracoDecoderPath:s,ktx2TranscoderPath:p,meshopt:f,project:u,onProjectChange:h,projectChangeDebounceMs:m=350,onModelUpload:C,onTextureUpload:B,onThumbnailCapture:w,hasThumbnail:P=!1,onEditLeaseChange:v,allowModelChange:d=!0,hideLicenseCheckingOverlay:x=!1}){let b=re(null),N=re(null),A=re(null),K=re(null),T=re(null),[z]=U(()=>u?Ta(u):null),[y,Q]=U(z?.url??null),[G,ee]=U(()=>u?u.models.filter(a=>a!==z).map(Na):[]),[le,M]=U(()=>u?u.models.map(a=>a.url):[]),[E,Ce]=U(z?.name??""),[Xe,X]=U(z),Ee=_e(()=>u&&le.length>1&&Xe?.tilesetUrl?{...Xe,tilesetUrl:null}:Xe,[u,le.length,Xe]),Ze=re(u?Aa(u):new Map),{selectedItem:O,setSelectedItem:D,multiSelectMode:$,setMultiSelectMode:fe,multiSelectedKeys:ue,setMultiSelectedKeys:mt,groupSelectionActive:Be,selectObject:eo,setSelection:Vn,toggleMultiSelect:Kt,exitMultiSelect:ki,clearSelection:Ms}=bu(),Ps=re({mode:!1,keys:[]}),Ci=re({shiftKey:!1,ctrlKey:!1,metaKey:!1}),[_n,$u]=U(null);Ps.current={mode:Be,keys:ue};let te=au(z?.objectBindings??{}),q=te.value,Do=te.setValue,Mi=re("free");uu({bindings:q,multiSelectMode:Be,selectedItem:O,multiSelectedKeys:ue,setSelectedItem:D,setMultiSelectedKeys:mt});let Ie=te.mergeSources,ho=te.setMergeSourcesUntracked;Le(()=>{z?.mergeModels?.length&&ho(On(z))},[z,ho]);let[Te,to]=U(!1),[Pi,Kn]=U(null),Uu=_e(()=>Pi?{target:Pi}:null,[Pi]);Le(()=>{Kn(null)},[y]),Le(()=>{fe(!1),mt([])},[y]);let[Bi,xo]=U(null);Le(()=>xo(null),[O,y]),Le(()=>{Kr(null),qr(null)},[y]);let[Vu,Lo]=U(null),[Bs,_u]=U(!1),[Pr,W]=U(""),[Br,J]=U("default"),[Ku,Ts]=U(null),Gu=Z(()=>Ts(null),[]),[Rs,Ti]=U("{}"),[Ns,Ri]=U("{}"),[qu,Ni]=U(null),[Wu,Ai]=U(null),[Yu,Gn]=U(!1),vo=hr("left",{size:296,min:220,max:480,edge:"right"}),oo=hr("inspector",{size:320,min:300,max:560,edge:"left"}),Tr=hr("dock",{size:300,min:160,max:640,edge:"top",open:!1}),[Et,Rr]=U("outliner"),[Oi,As]=U("sequences"),[Os,Es]=U("general"),[js,Nr]=U(!1),[Ar,Ju]=U(!0),[Xu,Or]=U(!1),[Zu,Er]=U(!1),[qn,Gt]=U("bindings"),[no,Is]=U({identity:!0,basics:!0,material:!0,decals:!0,actions:!0,camera:!1,transform:!0,metrics:!0,metadata:!0}),[Qu,eb]=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}),io=a=>Is(l=>({...l,[a]:!l[a]})),tb=a=>eb(l=>({...l,[a]:!l[a]})),[Ei,zs]=U(null),[yo,jr]=U(!1),[kt,un]=U("object"),[bn,Ir]=U("model"),[Ds,Ls]=U(null),[Fs,Hs]=U(!1),[$s,ob]=U(null),Us=vo.setOpen,Vs=Z(()=>{Us(!0),Rr("measure"),Hs(!0)},[Us]),[nb,ib]=U("metalness"),[rb,zr]=U(ws()),_s=re(null),[Ks,ab]=U(!1),[Dr,sb]=U(!0),[Lr,lb]=U(!0),[db,Gs]=U(!1),[Wn,qs]=U(null),[Fo,Fr]=U(null),[cb,Hr]=U(!1),ji=re(null),Ii=re({modelUrl:y,modelName:E,modelOrder:le,parkedModels:G});Ii.current={modelUrl:y,modelName:E,modelOrder:le,parkedModels:G};let[pb,gn]=U(!1),[wo,$r]=U(null),[ro,zi]=U("select"),ub=ro==="move"||ro==="rotate",bb=ro==="scale",[Ws,gb]=U("world"),Ct=re({}),Ne=di(u&&z?dr(u.sceneConfig,z):Mo),Ke=di(u?Ra(u):qo),[Ys,mn]=U([]),dt=_e(()=>({...Ke.value,placements:{...Object.fromEntries(Ys.map(a=>[a,{deleted:!0}])),...Ke.value.placements}}),[Ke.value,Ys]),[fn,hn]=U(!1),Js=re(null),oe=Ne.value,jt=Ne.setValue,mb=Z(a=>{let l=Mn(a);Ne.setValueAsStep(g=>({...g,selectionSets:l}))},[Ne.setValueAsStep]),Di=Ne.setValueUntracked,Ur=Z(a=>{let l=et(oe,a.modelSettings);a.sceneHistory?Ne.restoreSnapshot({...a.sceneHistory,present:l}):Ne.reset(l)},[oe,Ne.restoreSnapshot,Ne.reset]),{hasEdits:fb,markSessionEdited:ct,resetSessionEdits:Vr}=mu(te.edits,Ne.edits+Ke.edits),[Ho,Xs]=U(!1),[hb,xb]=U(.5),[_r,vb]=U(!0),[xn,Kr]=U(null),vn=xn??{bindings:te.baseline,sceneConfig:Ne.baseline},[Gr,yb]=U("modelObjectId"),[Li,qr]=U(null),Yn=_e(()=>Ho?Cd({objectBindings:vn.bindings,sceneConfig:vn.sceneConfig},{objectBindings:q,sceneConfig:oe},{matchBy:Gr}):null,[Ho,vn.bindings,vn.sceneConfig,q,oe,Gr]),Zs=_e(()=>Yn&&_r?{before:wa(Yn,"before",Li),after:wa(Yn,"after",Li)}:null,[Yn,Li,_r]),[Qs,Wr]=U("orbit"),[wb,el]=U(!1),Yr=re(void 0),Jr=Z(()=>{el(!0),clearTimeout(Yr.current),Yr.current=setTimeout(()=>el(!1),5e3)},[]);Le(()=>()=>clearTimeout(Yr.current),[]),Le(()=>{y&&!Te&&Jr()},[y,Te,Jr]);let qe=Qs==="pointerLock",[tl,Sb]=U(null),ol=re(null),kb=tl?.objectKey===O&&tl?.textureKey==="texture",[Cb,yn]=U(null),[Mb,Xr]=U(null),$o=pd(i,r,t),Uo=ld($o.tier);Mi.current=Uo;let nl=dd.models[Uo],Pb=_e(()=>({isInsideEditor:!0,activeTab:kt,activeSubTab:bn,tier:Uo,setActiveTab:un,setActiveSubTab:Ir,measurementPanelTarget:Ds,setMeasurementPanelTarget:Ls,measurementsPanelOpen:Fs,setMeasurementsPanelOpen:Hs,openMeasurementsPanel:Vs,xrToolsTarget:$s,annotating:Et==="annotations"}),[kt,bn,Uo,Ds,Fs,Vs,$s,Et]),Qe=re(null),wn=re(0),Mt=re(0),il=re(u?`${u.id}:${u.revision}`:null),rl=re(null),Bv=re(!1),Fi=re(!1),Hi=re(u?En(u):null),Zr=re(!1),$i=re(new Set),Ui=re(new Map),Vi=re(void 0),So=re(0),Bb=rd(Vu,So.current===100),Fe=re(null),rt=re(u?{requestId:0,modelName:z.name??"model",modelUrl:z.url,storedBindings:z.objectBindings,streaming:!!z.tilesetUrl}:null),We=re(z?{model:{kind:"url",url:z.url,name:z.name??"model"}}:null),_i=re(new Set),ao=re(new Map);lu(te.snapshot,G,{modelUrl:y,modelSourceRef:We,uploadedFilesRef:ao});let Jn=re(null),Tb=re(!1),so=re(null),Pt=re(new Map),[Qr,al]=U(0),ko=_e(()=>new Map(le.map(a=>{let l=a===y?We.current?.model:G.find(g=>g.url===a)?.sessionModel;return[a,l?Yt(l):`url:${a}`]})),[le,y,G]),Xn=a=>dt.placements[ko.get(a)??`url:${a}`]??{},ve=_e(()=>le.map((a,l)=>({id:ko.get(a)??`url:${a}`,url:a,name:Xn(a).label??(a===y?E:G.find(g=>g.url===a)?.name)??`Asset ${l+1}`,placement:Xn(a),ready:Pt.current.has(a)})).filter(a=>!a.placement.deleted),[le,y,E,G,dt,ko,Qr]),sl=Tt(Uo,"models",ve.length),lo=_e(()=>{let a=eu(ve.map(l=>l.name));return new Map(ve.map((l,g)=>[l.url,a[g]]))},[ve]),[ea,Rb]=U(!1),[ll,dl]=U(null),[Nb,cl]=U(null),Ab=Z(()=>{let a=y?Pt.current.get(y):void 0;!a||!y||dl({url:y,report:td(a,{source:{...ed(a),name:E},scope:Ee?.tilesetUrl?"resident-tiles":"asset"})})},[y,E,Ee?.tilesetUrl]);Le(()=>{cl(null)},[y,ea]);let{materialVariantGroups:pl,objectsWithoutUvs:ul,hierarchy:Ob}=vu({modelUrl:y,scenesRef:Pt,sceneRevision:Qr,streaming:!!Ee?.tilesetUrl});Le(()=>{let a=new Set(ve.map(l=>l.url));for(let l of Pt.current.keys())a.has(l)||Pt.current.delete(l)},[ve]),xu({enabled:!Ee?.tilesetUrl,modelUrl:y,bindings:q,mergeSources:Ie,parkedModels:G,scenesRef:Pt,sceneRevision:Qr,setBindings:te.setValueUntracked,setParkedModels:ee});let Vo=re(null),[Eb,jb]=U(null),[bl,Ib]=U({}),zb=_e(()=>{if(!Be||ue.length===0||!Vo.current)return null;let l=ue.filter(g=>q[g]&&!q[g].removed).map(g=>bl[g]).filter(g=>!!g);return l.length>0?l:null},[Be,ue,bl,q]),{cameraState:Re,resetView:gl,focusObject:Sn,fitScene:ml,setCameraState:Ki,handleCameraChange:fl,handleViewerReady:Db}=Dl(),{markThumbnailOutdated:Lb,noteThumbnailActivity:hl}=pu({onCapture:w,hasThumbnail:P,viewerRef:Vo,isModelLoading:()=>!y||!!rt.current}),Fb=Z((...a)=>{hl(),fl(...a)},[fl,hl]),xl=Z(a=>{qe||Ki({position:a.position,target:a.target,fov:a.fov??Re?.fov??null,zoom:a.zoom??Re?.zoom??1,azimuthAngle:a.azimuthAngle,polarAngle:a.polarAngle},!0)},[qe,Ki,Re]),It=Bd(),Hb=_e(()=>ve.map(a=>a.url),[ve]),zt=bc(Hb),Gi=mc({modelUrl:y,sceneConfig:oe,setSceneConfig:jt,setSceneConfigUntracked:Di,parkedModels:G,setParkedModels:ee,animations:zt,markSessionEdited:ct}),vl=kt==="configure"&&!yo&&Ei&&oe.product,$b=_e(()=>vl&&oe.product?{...oe,product:{...oe.product,selections:Ei}}:oe,[vl,oe,Ei]),Ub=Z(a=>jt(l=>({...a,product:l.product})),[jt]);Le(()=>{kt!=="configure"&&zs(null)},[kt]),Le(()=>{if(!yo)return;let a=l=>{l.key==="Escape"&&jr(!1)};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[yo]);let Me=O?q[O]??null:null,ta=Me?.style?.material,yl=!ul.has(Me?.modelObjectId??O??""),Vb=_e(()=>{if(!(ve.length<2))return ve.map(a=>({url:a.url,label:lo.get(a.url)??a.name,bindings:a.url===y?q:G.find(l=>l.url===a.url)?.bindings??{},isActive:a.url===y}))},[ve,lo,y,q,G]),Zn=_e(()=>{let a=[];return ve.forEach((l,g)=>{let S=l.url,k=S===y,I=k?void 0:G.find(_=>_.url===S),F=lo.get(S)||l.name||`Asset ${g+1}`;a.push({kind:"model",url:S,label:F,name:k?E:I?.name??"Untitled model",isActive:k}),(k?Ie:I?.mergedModelSources??[]).forEach(_=>{a.push({kind:"merge",url:_.url,label:"Merged nodes",name:Qt(_.namePrefix),ownerLabel:F})})}),u&&ve.length<2?a.filter(l=>l.kind!=="model"):a},[u,ve,y,E,G,Ie]),oa=_e(()=>Ie.map(a=>({url:a.url,namePrefix:a.namePrefix})),[Ie]),_b=_e(()=>(u?le.length<2:le.length<1)?void 0:le.map((l,g)=>{let S=dt.placements[ko.get(l)??`url:${l}`]??{},k={transform:S,visible:S.visible!==!1&&!S.deleted,label:S.label};if(l===y)return{url:l,label:lo.get(l)??k.label??(E||`Model ${g+1}`),transform:k.transform,visible:k.visible,objectBindings:q,originalNodePoses:Ct.current,mergeModels:oa};let F=G.find(H=>H.url===l);return{url:l,label:lo.get(l)??k.label??(F?.name||`Model ${g+1}`),transform:k.transform,visible:k.visible,objectBindings:F?.bindings??{},originalNodePoses:F?.originalTransforms,sceneConfig:et(oe,F?.modelSettings),mergeModels:(F?.mergedModelSources??[]).map(H=>({url:H.url,namePrefix:H.namePrefix}))}}).filter(l=>!dt.placements[ko.get(l.url)??`url:${l.url}`]?.deleted),[u,le,y,E,q,G,oa,oe,dt,ko,lo]);Le(()=>{let a=A.current;if(a)return a.style.setProperty("--bb-canvas-hint-top",Ho?"48px":"12px"),()=>{a.style.removeProperty("--bb-canvas-hint-top")}},[Ho]);let Co=Me?.cameraState,Kb=Re?{position:Ua(Re.position),target:Ua(Re.target)}:null,Gb=Z(a=>{jt(l=>{let g=l.annotations.map(k=>k.id).join(","),S=a.map(k=>k.id).join(",");return g===S?l:a.length>l.annotations.length&&!Tt(Mi.current,"annotations",l.annotations.length)?(W(`More annotations require the ${va[Yo("annotations",l.annotations.length)]} plan or higher.`),J("error"),l):{...l,annotations:a}})},[]),qb=Z(a=>{yn(a?{annotation:a}:null)},[]);Le(()=>{if(!Me){Ti("{}"),Ri("{}"),Ni(null),Ai(null);return}Ti($a(Me.metrics)),Ri($a(Me.metadata)),Ni(null),Ai(null)},[Me]),Le(()=>{let a=ws(ta);if(_s.current!==O){_s.current=O,zr(a);return}zr(l=>{let g=!1,S={...l};for(let k of Au)a[k]&&!l[k]&&(S[k]=!0,g=!0);return g?S:l})},[O,ta]),Le(()=>()=>{Qe.current?.cleanup(),Fe.current&&clearTimeout(Fe.current)},[]);let qi=Z((a,l)=>{let g=ni(a);if(l){let S=new Map(Object.values(l).map(k=>[k.modelObjectId,k]));for(let k of a){let I=S.get(k);I&&(g[k]=I)}}return g},[]);Le(()=>{if(!u)return;let a=`${u.id}:${u.revision}`;if(il.current===a)return;il.current=a,Ze.current=Aa(u);let l=u.models.find(ne=>ne.url===y),g=l&&!u.composition.placements[Qo(l.url)]?.deleted?l:Ta(u),S=dr(u.sceneConfig,g),k=y!==g.url||Xe?.tilesetUrl!==g.tilesetUrl||Xe?.assetVersion!==g.assetVersion,I=En(u);if(!k&&$i.current.delete(I)){Hi.current=I;return}$i.current.clear();let F=!cr(q,g.objectBindings),H=!cr(oe,S);X(g),Ce(g.name??"model");let _=g.objectBindings;if(F){let ne=rl.current;_=ne?qi(ne,g.objectBindings):g.objectBindings,te.reset(_)}else _=q;H&&Ne.reset(S),ee(ne=>u.models.filter(Pe=>Pe.url!==g.url).map(Pe=>{let ft=ne.find(Dt=>Dt.url===Pe.url);if(!ft)return Na(Pe);let ke=JSON.stringify(ft.mergedModelSources.map(Dt=>Dt.url))===JSON.stringify((Pe.mergeModels??[]).map(Dt=>Dt.url));return{...ft,name:Pe.name??ft.name,bindings:Pe.objectBindings,modelSettings:Pe.modelSettings,mergedModelSources:ke?ft.mergedModelSources:On(Pe),bindingHistory:ke?ft.bindingHistory:void 0}})),M(u.models.map(ne=>ne.url));let ce=(g.mergeModels??[]).map(ne=>ne.url);if(JSON.stringify(Ie.map(ne=>ne.url))!==JSON.stringify(ce)&&(ho(On(g)),te.clearHistory()),cr(Ke.value,u.composition)||Ke.reset(Ra(u)),k){It.clearAnimations();let ne=++Mt.current;rt.current={requestId:ne,modelName:g.name??"model",modelUrl:g.url,storedBindings:g.objectBindings,streaming:!!g.tilesetUrl},We.current={model:{kind:"url",url:g.url,name:g.name??"model"}},so.current=null,D(null),to(!0),Q(g.url)}Hi.current=En({models:u.models.map(ne=>ne===g?{...ne,objectBindings:_}:ne),composition:u.composition,sceneConfig:u.sceneConfig})},[Xe,q,qi,Ke,Ie,u,y,oe,te,Ne,ho,It.clearAnimations]);let na=re(h);na.current=h;let wl=re(B);wl.current=B,Le(()=>{if(!u||!na.current||!y||rt.current)return;let a=()=>Jd({project:u,modelUrl:y,modelName:E,bindings:q,sceneConfig:oe,mergedModelSources:Ie,parkedModels:G,modelOrder:le,composition:dt,sources:Ze.current});Fi.current&&(Fi.current=!1,Hi.current=En({...a(),composition:u.composition,sceneConfig:u.sceneConfig}));let l=window.setTimeout(()=>{if(Zr.current)return;let g=a(),S=En(g);if(S===Hi.current||$i.current.has(S))return;let k=wl.current,I=k?Zo(g.models).size+Zo(g.sceneConfig).size:0;if(k&&I>0){Zr.current=!0;let F=Zo(g.sceneConfig,Zo(g.models));Promise.all([...F].map(async H=>{if(!Ui.current.has(H))try{Ui.current.set(H,await k(await Zd(H),H))}catch(_){W(_ instanceof Error?_.message:"Could not save an image."),J("error"),Ui.current.set(H,"")}})).then(()=>{Zr.current=!1;let H=_=>lr(_,Ui.current);te.setValueUntracked(H),Ne.setValueUntracked(H),ee(_=>_.map(ce=>({...ce,bindings:H(ce.bindings),modelSettings:H(ce.modelSettings)})))});return}$i.current.add(S),na.current?.(g,"local"),Lb()},m);return()=>window.clearTimeout(l)},[q,dt,Ie,E,le,y,G,u,m,oe]);let _o=qn==="assets"?Ke:qn==="scene"?Ne:te;Le(()=>{let a=l=>{l.key.toLowerCase()!=="z"||!(l.metaKey||l.ctrlKey)||Hu(l.target)||(l.preventDefault(),l.shiftKey?_o.redo():_o.undo())};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[_o]);let Wi=!u&&d,{handleTextureUpload:Wb}=du({composition:dt,autosaveEnabled:Wi,hasEdits:fb,modelUrl:y,bindings:q,sceneConfig:oe,parkedModels:G,mergedModelSources:Ie,modelOrder:le,onTextureUpload:B,modelSourceRef:We,pendingLoadRef:rt,storedModelKeysRef:_i,uploadedFilesRef:ao,pendingAutosaveRef:Jn,autosaveFailureShownRef:Tb,setStatusMessage:W,setStatusTone:J});Le(()=>{Te||Br==="default"||Ts({id:Date.now(),text:Pr,tone:Br})},[Pr,Br,Te]);let qt=_e(()=>Object.keys(q),[q]),Yb=_e(()=>!O||!Me?null:Me.id.trim()?Object.entries(q).some(([g,S])=>g!==O&&S.id===Me.id)?"Another binding already uses this ID.":null:"ID is required.",[q,O,Me]),Bt=(a,l)=>{Do(g=>{let S=Ps.current,k=S.mode&&S.keys.includes(a)?S.keys.filter(F=>g[F]):[a];if(k.length<=1)return{...g,[a]:l(g[a],a)};let I={...g};for(let F of k){let H=g[F];I[F]={...l(H,F),id:H.id,modelObjectId:H.modelObjectId}}return I})},ia=(a,l)=>{Bt(a,g=>{let S=ys(l(g.style?.material));return Ss(g,S)})},Jb=(a,l,g)=>{ia(a,S=>({...S,[l]:g?{path:g}:void 0}))},Xb=(a,l)=>{zr(g=>({...g,[a]:l})),!l&&O&&Bt(O,g=>{let S=ys(Eu(g.style?.material,a));return Ss(g,S)})},ra=Z((a,l,g)=>{let{bindings:S,originalTransforms:k,nodeNames:I}=vi(a,g);Ct.current=k,te.reset(ln(a,g??{},Ie,S)),D(I[0]??null),g||Di(H=>({...H,annotations:[]})),W(`Generated ${I.length} bindings from ${l}.`),J("success"),Fe.current&&clearTimeout(Fe.current);let F=setTimeout(()=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{Fe.current===F&&(So.current=100,Lo(100),Fe.current=setTimeout(()=>{Fe.current=null,to(!1),Lo(null)},400))})})},0);Fe.current=F},[te,Di,Ie]),aa=(a,l,g,S)=>{Jn.current?.();let k=++Mt.current;Vr(),Ke.reset(qo),mn([]),u||Ne.reset(a!==y?et(oe):oe),a!==y&&It.clearAnimations(),G.forEach(H=>H.resolved?.cleanup()),ee([]),M([a]),ho([]),to(!0),Lo(null),So.current=0,Fe.current&&(clearTimeout(Fe.current),Fe.current=null),Vi.current=g;let I=g?g/1048576:0;W(I>=100?`Reading the file. At ${Math.round(I)} MB, this can take a while.`:"Reading the file and generating bindings."),J("default"),Ce(l),X(S??{url:a,name:l}),yn(null);let F=so.current;if(a===y&&F?.url===a){rt.current=null,ra(F.scene,l);return}rt.current={requestId:k,modelName:l,modelUrl:a,streaming:!!S?.tilesetUrl},Q(a),te.reset({}),D(null)},Zb=Z(a=>{y&&Pt.current.get(y)!==a&&(Pt.current.set(y,a),al(g=>g+1));let l=rt.current;if(!(l&&l.requestId!==Mt.current)&&(y&&(so.current={url:y,scene:a}),xo(null),Kn(null),!!l)){if(rt.current=null,l.streaming){W(`Streaming ${l.modelName}.`),J("success"),to(!1);return}l.storedBindings&&(Fi.current=!0),ra(a,l.modelName,l.storedBindings),l.restoring&&W(`Restored your last session with ${l.modelName}.`)}},[ra,y]),Qb=Z(a=>{if(!Ee?.tilesetUrl)return;let l=a.map(k=>k.name);if(l.length===0)return;rl.current=l,Fi.current=!0;let g=u?.models.find(k=>k.url===y)?.objectBindings,S=qi(l,g);te.reset(S),D(k=>k??l[0]??null),W(`Streaming ${l.length} bindable objects.`),J("success"),to(!1)},[qi,te,y,u,Ee]),eg=Z(a=>{let l=rt.current;if(!(l&&l.requestId!==Mt.current)){if(rt.current=null,console.error(a),l?.restoring)We.current=null,Q(null),W(Cs(l.modelName));else if(l)W(od(a)?`${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:g}=or(a,y??"",Qe.current?.format);W(`Could not read ${E||"the model"}. ${g}`)}J("error"),Fe.current&&(clearTimeout(Fe.current),Fe.current=null),So.current=0,to(!1),Lo(null)}},[y,E]),tg=Z(a=>{let l=null;if(a.lengthComputable&&a.total>0)l=a.loaded/a.total*100;else{let S=Vi.current;S&&S>0&&(l=a.loaded/S*100)}if(l===null)return;let g=Math.min(99,Math.floor(l));g>So.current&&(So.current=g),Lo(S=>l>=99.5?100:Math.max(S??0,g)),l>=99.5&&W(S=>S.startsWith("Finalizing")?S:"Finalizing: parsing geometry and textures.")},[]),og=Z(a=>{It.handleAnimationsReady(a),y&&zt.handleModelAnimationsReady(y,a)},[It,y,zt.handleModelAnimationsReady]),Tv=async()=>{Qe.current?.cleanup(),Qe.current=null,We.current={model:{kind:"url",url:Du,name:"room.glb"}},await aa(Du,"room.glb")},Sl=async a=>{if(!d)return;if(a.name.toLowerCase().endsWith(".ri.zip")){await Al(a);return}if(C){try{to(!0),W(`Uploading ${a.name}...`),J("default");let S=await C(a);Ze.current.set(S.url,S),We.current={model:{kind:"url",url:S.url,name:S.name??a.name}},await aa(S.url,S.name??a.name,a.size,S)}catch(S){to(!1),W(S instanceof Error?S.message:`Could not upload ${a.name}.`),J("error")}return}let l;try{l=await Po(a)}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."),J("error");return}Qe.current?.cleanup(),Qe.current=l;let g=ks();ao.current.set(g,a),We.current={model:{kind:"file",key:g,name:l.name},file:a},await aa(l.url,l.name,a.size,{url:l.url,name:l.name})},ng=async a=>{let l=a.target.files?.[0];l&&(await Sl(l),a.target.value="")},Yi=()=>{Jn.current=null,ct(),Qe.current?.cleanup(),Qe.current=null,so.current=null,rt.current=null,We.current=null,It.clearAnimations(),Ct.current={},wn.current=0,Gn(!1),Fe.current&&(clearTimeout(Fe.current),Fe.current=null),So.current=0,Lo(null),Vi.current=void 0,Q(null),Ce(""),G.forEach(a=>a.resolved?.cleanup()),ee([]),M([]),Ke.reset(qo),mn([]),ho([]),X(null),D(null),yn(null),te.reset({}),Ti("{}"),Ri("{}"),Ni(null),Ai(null),Xr(null),zi("select"),Di(a=>et(a)),W(""),J("default")},kl=a=>u?{...a,bindingHistory:void 0}:a,ig=()=>{Zn.length>1?gn(!0):Yi()},rg=()=>{gn(!1)},ag=a=>{if(gn(!1),le.length<=1){Yi();return}if(!le.includes(a))return;if(ct(),a!==y){let I=G.find(F=>F.url===a);I?.resolved?.cleanup(),ee(F=>F.filter(H=>H.url!==a)),M(F=>F.filter(H=>H!==a)),W(`Removed ${I?.name??"the model"}.`),J("success");return}let l=le.filter(I=>I!==a),g=l[0],S=G.findIndex(I=>I.url===g),k=G[S];if(!k){Yi();return}Qe.current?.cleanup(),ee(I=>I.filter((F,H)=>H!==S)),M(l),Qe.current=k.resolved??null,We.current={model:k.sessionModel??{kind:"url",url:k.url,name:k.name}},so.current=null,rt.current=null,Ct.current=k.originalTransforms,It.clearAnimations(),Ur(k),Q(k.url),Ce(k.name),X(Ze.current.get(k.url)??{url:k.url,name:k.name}),te.restoreModel(k),D(Object.keys(k.bindings)[0]??null),yn(null),W(`Removed the model \u2014 now viewing ${k.name}.`),J("success")},sg=a=>{gn(!1);let l=Ie.find(k=>k.url===a);if(l){ct(),te.removeMerge(a),u&&te.clearHistory(),W(`Removed ${Qt(l.namePrefix)}.`),J("success");return}let g=G.find(k=>k.mergedModelSources.some(I=>I.url===a));if(!g)return;let S=g.mergedModelSources.find(k=>k.url===a);S&&(ct(),ee(k=>k.map(I=>I.url!==g.url?I:kl(cs(I,F=>ds(F,a))))),W(`Removed ${Qt(S.namePrefix)}.`),J("success"))},Cl=()=>{b.current?.click()},sa=()=>{Hr(!0)},lg=a=>{let l=a.target.files?.[0];a.target.value="";let g=ji.current;ji.current=null,!(!l||!d||!g)&&(g.mode==="separate"?pg(l):ug(l,g.targetUrl))},dg=Z(()=>{ji.current=null,Hr(!1)},[]),cg=Z(a=>{ji.current=a,Hr(!1),N.current?.click()},[]),la=Z(async a=>{if(u&&C){W(`Uploading ${a.name}...`),J("default");let S=await C(a);Ze.current.set(S.url,S);let k=S.name??a.name;return{resolved:{url:S.url,name:k,format:"glb",cleanup:()=>{}},sessionModel:{kind:"url",url:S.url,name:k}}}let l=await Po(a),g=ks();return ao.current.set(g,a),{resolved:l,sessionModel:{kind:"file",key:g,name:l.name}}},[u,C]),pg=Z(async a=>{if(!Tt(Mi.current,"models",Ii.current.modelOrder.length)){W("Your plan has no room for another model in this project. Upgrade to add more."),J("error");return}let l,g;try{({resolved:l,sessionModel:g}=await la(a))}catch(S){W(S instanceof Error?S.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, or .zip asset."),J("error");return}ee(S=>[...S,{url:l.url,name:l.name,bindings:{},originalTransforms:{},resolved:l,sessionModel:g,mergedModelSources:[]}]),M(S=>[...S,l.url]),ct(),W(`Added ${l.name} as a separate model.`),J("success")},[ct,la]),ug=Z(async(a,l)=>{let g,S;try{({resolved:g,sessionModel:S}=await la(a))}catch(_){W(_ instanceof Error?_.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, or .zip asset."),J("error");return}let k=Ii.current,I=k.parkedModels.find(_=>_.url===l);if(!k.modelOrder.includes(l)||l!==k.modelUrl&&!I){g.cleanup(),W("The destination model was removed. Choose a model and add the file again."),J("error");return}let F={url:g.url,resolved:g,sessionModel:S,nodeNames:[],loadState:"loading"};l===k.modelUrl?(te.addMerge(_=>({...F,namePrefix:ss(g.name,_.mergeSources,_.bindings)})),u&&te.clearHistory()):ee(_=>{let ce=_.findIndex(Pe=>Pe.url===l);if(ce===-1)return _;let ne=[..._];return ne[ce]=kl(cs(ne[ce],Pe=>({...Pe,mergeSources:[...Pe.mergeSources,{...F,namePrefix:ss(g.name,Pe.mergeSources,Pe.bindings)}]}))),ne});let H=l===k.modelUrl?k.modelName:I?.name;ct(),W(`Merging ${g.name} into ${H||"the model"}...`),J("default")},[te.addMerge,ct]),bg=Z((a,l)=>{let g=Ie.find(_=>_.url===a);if(g){let{bindings:_,originalTransforms:ce,nodeNames:ne}=ls(l,q);te.hydrateMerge(a,{nodeNames:ne,loadState:"loaded"},_),Ct.current={...Ct.current,...ce},W(`Merged ${ne.length} node${ne.length===1?"":"s"} from ${g.namePrefix||"the added model"} into ${E||"the model"}.`),J("success");return}let S=G.find(_=>_.mergedModelSources.some(ce=>ce.url===a));if(!S)return;let k=S.mergedModelSources.find(_=>_.url===a);if(!k)return;let{bindings:I,originalTransforms:F,nodeNames:H}=ls(l,S.bindings);ee(_=>_.map(ce=>ce.url!==S.url?ce:{...ps(ce,a,{nodeNames:H,loadState:"loaded"},I),originalTransforms:{...ce.originalTransforms,...F}})),W(`Merged ${H.length} node${H.length===1?"":"s"} from ${k.namePrefix||"the added model"} into ${S.name||"the model"}.`),J("success")},[te.hydrateMerge,E,Ie,q,G]),gg=Z((a,l)=>{let g=Ie.find(k=>k.url===a)??G.flatMap(k=>k.mergedModelSources).find(k=>k.url===a);if(!g)return;te.hydrateMerge(a,{loadState:"failed"}),ee(k=>k.map(I=>I.mergedModelSources.some(F=>F.url===a)?ps(I,a,{loadState:"failed"}):I));let{detail:S}=or(l,a,g.resolved.format);W(`Could not merge ${g.resolved.name}. ${S} Remove the failed file using the Remove model menu.`),J("error")},[Ie,G,te.hydrateMerge]),mg=Z((a,l)=>{let g=G.find(k=>k.url===a);if(!g)return;let{detail:S}=or(l,a,g.resolved?.format);W(`Could not read ${g.name}. ${S} Remove the failed file using the Remove model menu.`),J("error")},[G]),fg=Z((a,l)=>{Pt.current.get(a)!==l&&(Pt.current.set(a,l),al(g=>g+1)),ee(g=>{let S=g.findIndex(H=>H.url===a);if(S===-1)return g;let{bindings:k,originalTransforms:I}=vi(l,g[S].bindings),F=[...g];return F[S]={...ru(F[S],k),bindings:ln(l,g[S].bindings,g[S].mergedModelSources,k),originalTransforms:{...I,...g[S].originalTransforms}},F})},[]),Ko=Z(a=>{if(a===y)return;let l=G.findIndex(k=>k.url===a);if(l===-1)return;let g=G[l];Jn.current?.(),ct();let S=y?{url:y,name:E,bindings:q,originalTransforms:Ct.current,resolved:Qe.current??void 0,sessionModel:We.current?.model,mergedModelSources:Ie,modelSettings:Bo(oe),bindingHistory:te.snapshot,sceneHistory:Ne.snapshot}:null;ee(k=>{let I=k.filter((F,H)=>H!==l);return S?[...I,S]:I}),Qe.current=g.resolved??null,We.current={model:g.sessionModel??{kind:"url",url:g.url,name:g.name}},so.current=null,rt.current=null,It.clearAnimations(),Ur(g),Ct.current=g.originalTransforms,Q(g.url),Ce(g.name),X(Ze.current.get(g.url)??{url:g.url,name:g.name}),te.restoreModel(g),D(Object.keys(g.bindings)[0]??null),yn(null)},[y,E,q,G,te,Ie,oe,Ne,Ur,It.clearAnimations,ct]),hg=()=>{K.current?.click()};Le(()=>{y&&ve.length&&!ve.some(a=>a.url===y)&&Ko(ve[0].url)},[y,ve,Ko]);let{handleExportBindings:Ml,handleExportSceneConfig:Pl,handleImportBindingsChange:xg,openSceneConfigImportPicker:vg,handleImportSceneConfigChange:yg}=Nu({bindings:q,setBindings:Do,sceneConfig:oe,setSceneConfig:jt,nodeKeys:qt,sceneConfigInputRef:T,setIsExporting:_u,setStatusMessage:W,setStatusTone:J}),wg=a=>{a.preventDefault(),a.stopPropagation(),!(Te||y)&&(wn.current+=1,Gn(!0))},Sg=a=>{a.preventDefault(),a.stopPropagation(),!(Te||y)&&(a.dataTransfer.dropEffect="copy",Gn(!0))},kg=a=>{a.preventDefault(),a.stopPropagation(),!(Te||y)&&(wn.current=Math.max(0,wn.current-1),wn.current===0&&Gn(!1))},Cg=async a=>{if(a.preventDefault(),a.stopPropagation(),wn.current=0,Gn(!1),Te||y)return;let l=a.dataTransfer.files?.[0];l&&await Sl(l)},Bl=(a,l,g)=>{if(!O)return;let S;try{S=JSON.parse(l)}catch{g("Invalid JSON");return}if(S===null||typeof S!="object"||Array.isArray(S)){g("Expected a JSON object");return}if(a==="metrics"&&Object.values(S).some(I=>typeof I!="number"||!Number.isFinite(I))){g("Metrics values must be numbers");return}Bt(O,k=>({...k,[a]:S})),g(null)},Tl=Z((a,l)=>{Wi&&An(a,l).catch(g=>console.warn("[BindingBuilder] Could not store decal image for autosave:",g))},[Wi]),Mg=_e(()=>{let a=so.current?.scene,g=(a&&O?ei(a,O):null)?.geometry;if(!g)return .2;g.boundingBox||g.computeBoundingBox();let S=g.boundingBox?.getSize(new nv),k=S?Math.max(S.x,S.y,S.z):0;return k>0&&Number.isFinite(k)?k/3:.2},[O,y,Te]),Pg=_e(()=>{if(!Bi?.moving)return null;let{nodeKey:a,decal:l}=Bi,g=q[a],S=g?.decals?.find(k=>k.id===l.id);return S?{objectId:g.modelObjectId??a,decal:S,onCancel:()=>xo(null),onCommit:k=>{Do(I=>{let F=I[a];return F?{...I,[a]:{...F,decals:F.decals?.map(H=>H.id===S.id?{...H,...k}:H)}}:I}),xo(null)}}:null},[q,Bi,Do]),Bg=Z((a,l)=>{if(!O)return;let g=q[O],S=g?.decals?.find(H=>H.id===a);if(!S)return;let k=Vo.current,I=k?.raw.nodes[g.modelObjectId??O],F=vd(I,k?.raw.controls.camera,S,l);if(!F){W("No visible surface in that direction. Try another arrow or rotate the view."),J("error");return}xo(null),Bt(O,H=>({...H,decals:H.decals?.map(_=>_.id===a?{..._,...F}:_)}))},[q,O,Bt]),Tg=Z(a=>{if(!a||a.moving){xo(a);return}let l=Vo.current,g=q[a.nodeKey],S=l?.raw.nodes[g?.modelObjectId??a.nodeKey],k=xd(S,l?.raw.controls.camera);if(!k){W("Could not find a surface on this object for the decal."),J("error");return}let I={...a.decal,...k};Do(F=>{let H=F[a.nodeKey];if(!H)return F;let _=(H.decals??[]).filter(ce=>ce.id!==I.id);return{...F,[a.nodeKey]:{...H,decals:[..._,I]}}}),xo({...a,moving:!0})},[q,Do]),Rg=Z((a,l)=>{let g=Object.entries(q).find(([H,_])=>_===a||H===a.modelObjectId||_.modelObjectId===a.modelObjectId)?.[0],S=g?q[g]?.decals?.find(H=>H.id===l):void 0;if(!g||!S)return;un("object"),Is(H=>({...H,decals:!0})),D(g);let{position:k,normal:I,...F}=S;setTimeout(()=>xo({nodeKey:g,decal:F,moving:!0}),0)},[q]),Ng=Z(a=>{let l=[...new Set(a)].filter(g=>q[g]&&!q[g].removed);Vn(l)},[q,Vn]),Ag=Z(a=>{let l=Ci.current;if(Ci.current={shiftKey:!1,ctrlKey:!1,metaKey:!1},qe){Wr("orbit");return}if(!a){eo(null);return}let g=Object.entries(q).find(([S,k])=>k===a||S===a.modelObjectId||k.modelObjectId===a.modelObjectId)?.[0]??null;eo(g,l)},[qe,q,eo]),da=Z(async a=>{if(qe){Wr("orbit");return}eo(a),!$&&(Xr(null),await Sn(a))},[qe,Sn,$,eo]),Og=Z(a=>{Xr(a?q[a]??null:null)},[q]),Eg=Z(()=>{if(qe){W("Camera positions aren't available while Pointer Lock is the active camera controller."),J("error");return}if(!O||!Re)return;let a={position:Re.position,target:Re.target,...Re.fov!=null?{fov:Re.fov}:{},zoom:Re.zoom};Bt(O,l=>({...l,cameraState:a}))},[qe,O,Re]),jg=Z(()=>{if(qe){W("Camera positions aren't available while Pointer Lock is the active camera controller."),J("error");return}!Co?.position||!Co?.target||Ki({position:Co.position,target:Co.target,fov:Co.fov??Re?.fov??null,zoom:Co.zoom??Re?.zoom??1},!0)},[qe,Co,Ki,Re]),Ig=Z(()=>{qe||O&&Bt(O,a=>({...a,cameraState:void 0}))},[qe,O]),Rl=Z(async()=>{if(qe){W("Reset view isn't available while Pointer Lock is the active camera controller."),J("error");return}await gl()},[qe,gl]),Qn=Z(async()=>{if(qe){W("Fit scene isn't available while Pointer Lock is the active camera controller."),J("error");return}await ml()},[qe,ml]),zg=Z(()=>{W("Texture position saved."),J("success"),ol.current?.()},[]),Dg=Z(a=>{qs(a),Gs(!0)},[]),Ji=Z(()=>{Gs(!1),qs(null)},[]),Lg=Z(()=>{if(Wn==="bindings"){if(!qt.length){Ji();return}let a=ni(qt,ul);te.reset(a,{asEdit:!0}),D(qt[0]??null),W("Object bindings reset to default values."),J("success")}else Wn==="assets"?(Ke.setValueAsStep(a=>({...a,gridSize:qo.gridSize,placements:Object.fromEntries(Object.entries(a.placements).map(([l,g])=>{let{position:S,rotation:k,scale:I,...F}=g;return[l,F]}))})),W("Asset placements reset to default values."),J("success")):Wn==="scene"&&(Ne.reset(Mo,{asEdit:!0}),W("Scene config reset to default values."),J("success"));Ji()},[Wn,qt,te,Ne,Ke,Ji]),Nl=Z(a=>{a.length>0&&$r(a)},[]),Fg=Z((a,l)=>{Gt("bindings"),te.setValueAsStep(g=>_p(g,a,l))},[te.setValueAsStep]),Hg=Z((a,l)=>{Gt("bindings"),te.setValueAsStep(g=>Kp(g,a,l))},[te.setValueAsStep]),$g=Z(()=>{$r(null)},[]),Ug=Z(()=>{let a=wo;if(!a||a.length===0)return;Gt("bindings");let l=new Set(a);te.setValueAsStep(g=>{let S={...g};for(let k of a)g[k]&&(S[k]={...g[k],removed:!0});return S}),D(g=>g&&l.has(g)?null:g),mt(g=>g.filter(S=>!l.has(S))),Kn(g=>g&&l.has(g)?null:g),W(a.length===1?`Deleted ${q[a[0]]?.label||a[0]}.`:`Deleted ${a.length} objects.`),J("success"),$r(null)},[wo,q,te.setValueAsStep]),Vg=Z(()=>{Fr(null)},[]),_g=async()=>{let a;try{a=await Wd()}catch(l){console.warn("[BindingBuilder] Could not read the saved session:",l),W("Couldn't read the saved session from this browser."),J("error");return}if(!a){W("No saved session in this browser. Sessions are saved when you edit a model or add another one."),J("error");return}Fr(a)},ca=async(a,l)=>(await Promise.all(a.map(async({entry:S,file:k})=>{if(S.model.kind==="url"&&u)return On({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 I=await Po(k);return l.set(S.model.key,k),{url:I.url,namePrefix:S.namePrefix,resolved:I,sessionModel:S.model,nodeNames:[],loadState:"loading"}}catch(I){return console.warn(`[BindingBuilder] Could not restore merged model "${S.model.name}":`,I),null}}))).filter(S=>S!==null),Kg=async(a,l,g)=>{let S=await Promise.all(a.map(async({entry:I,file:F,mergeFiles:H})=>{if(await Si(I.modelSettings?.product),I.model.kind==="url")return{url:I.model.url,name:I.model.name,bindings:await cn(I.bindings),originalTransforms:I.originalTransforms,modelSettings:I.modelSettings,sessionModel:I.model,mergedModelSources:await ca(H,g)};if(!F)return console.warn(`[BindingBuilder] Could not restore parked model "${I.model.name}" \u2014 its file is no longer in this browser's storage.`),null;try{let _=await Po(F);return g.set(I.model.key,F),{url:_.url,name:I.model.name,bindings:await cn(I.bindings),originalTransforms:I.originalTransforms,modelSettings:I.modelSettings,resolved:_,sessionModel:I.model,mergedModelSources:await ca(H,g)}}catch(_){return console.warn(`[BindingBuilder] Could not restore parked model "${I.model.name}":`,_),null}})),k=await ca(l,g);return{parkedModels:S.filter(I=>I!==null),mergedModelSources:k}},pa=(a,l)=>{Ke.setValue(g=>({...g,placements:{...g.placements,[a]:{...g.placements[a],...l}}}))},Gg=async a=>{if(fn||!d||!sl)return;let l=a===y?{url:a,name:E,bindings:q,originalTransforms:Ct.current,resolved:Qe.current??void 0,sessionModel:We.current?.model,mergedModelSources:Ie,modelSettings:Bo(oe)}:G.find(k=>k.url===a);if(!l?.sessionModel)return;if(u){let k=`${a.split("#")[0]}#copy-${crypto.randomUUID()}`,I=Qo(k),F=Ze.current.get(a);Ze.current.set(k,{...F,url:k});let H=`${l.name} copy`,_=structuredClone(l.modelSettings);_?.measurements&&(_.measurements.items=_.measurements.items.map(ke=>({...ke,modelId:I}))),ee(ke=>[...ke,{...l,url:k,name:H,resolved:void 0,sessionModel:{kind:"url",url:k,name:H},bindings:structuredClone(l.bindings),originalTransforms:structuredClone(l.originalTransforms),modelSettings:_,mergedModelSources:l.mergedModelSources.map(Dt=>({...Dt,loadState:"loading"})),bindingHistory:void 0,sceneHistory:void 0}]),M(ke=>[...ke,k]),mn(ke=>[...ke,I]);let ce=Xn(a),[ne,Pe,ft]=ce.position??[0,0,0];Ke.setValueAsStep(ke=>({...ke,placements:{...ke.placements,[I]:{...ce,deleted:!1,label:`${ce.label??l.name} copy`,position:[ne+dt.gridSize,Pe,ft]}}})),ct(),W(`Duplicated ${l.name}.`),J("success");return}hn(!0);let g=Mt.current,S=[];try{let I=(l.sessionModel.kind==="file"?ao.current.get(l.sessionModel.key):void 0)??new File([await(await fetch(l.url)).blob()],l.name),F=await Po(I);S.push(F);let H=ks(),_=`file:${H}`,ce=[];for(let ye of l.mergedModelSources){if(ye.sessionModel.kind!=="file")throw new Error("Cannot duplicate a merged source without its original file.");let at=ao.current.get(ye.sessionModel.key);if(!at)throw new Error("An added source file is unavailable.");let Lt=await Po(at);S.push(Lt),ce.push({...ye,resolved:Lt,url:Lt.url,loadState:"loading"})}if(g!==Mt.current||!Ii.current.modelOrder.includes(a)){S.forEach(ye=>ye.cleanup());return}ao.current.set(H,I);let ne=structuredClone(l.modelSettings);ne?.measurements&&(ne.measurements.items=ne.measurements.items.map(ye=>({...ye,modelId:_}))),ee(ye=>[...ye,{...l,url:F.url,name:`${l.name} copy`,resolved:F,sessionModel:{kind:"file",key:H,name:I.name},bindings:structuredClone(l.bindings),originalTransforms:structuredClone(l.originalTransforms),modelSettings:ne,mergedModelSources:ce,bindingHistory:void 0,sceneHistory:void 0}]),M(ye=>[...ye,F.url]),mn(ye=>[...ye,_]);let Pe=Xn(a),[ft,ke,Dt]=Pe.position??[0,0,0];Ke.setValueAsStep(ye=>({...ye,placements:{...ye.placements,[_]:{...Pe,deleted:!1,label:`${Pe.label??l.name} copy`,position:[ft+dt.gridSize,ke,Dt]}}})),ct(),W(`Duplicated ${l.name}.`),J("success")}catch(k){S.forEach(I=>I.cleanup()),W(k instanceof Error?k.message:"Could not duplicate asset."),J("error")}finally{hn(!1)}},qg=a=>{if(ve.length<2||!d)return;let l=ve.find(g=>g.url===a);l&&(a===y&&Ko(ve.find(g=>g.url!==a).url),Ke.setValueAsStep(g=>({...g,placements:{...g.placements,[l.id]:{...g.placements[l.id],deleted:!0}}})))},Al=async a=>{if(!(fn||!d)){if(!st(Mi.current,"sceneBundle")){W(`Importing a complete scene requires the ${va.starter} plan or higher.`),J("error");return}hn(!0);try{let l=await nc(a);if(u){if(!C)throw new Error("This project can't accept new models.");let g=S=>l.session.composition?.placements[Yt(S)]?.deleted;if(1+l.parkedFiles.filter(S=>!g(S.entry.model)).length>nl)throw new Error(`Your plan allows ${nl} models per project. Upgrade to import this scene.`);W(`Uploading the models in ${a.name}...`),J("default"),l=await Qd(l,async S=>{let k=await C(S);return Ze.current.set(k.url,k),k})}await Ol(l),ct()}catch(l){W(l instanceof Error?l.message:"Could not load scene bundle."),J("error")}finally{hn(!1)}}},Wg=async()=>{let a=We.current;if(!(!a||!y||fn)){hn(!0);try{let l=k=>({model:k.sessionModel,namePrefix:k.namePrefix}),g={model:a.model,bindings:q,sceneConfig:oe,composition:dt,mergeModels:Ie.map(l),parkedModels:G.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:le.map(k=>ko.get(k)).filter(Boolean)},S=await oc(g,new Map(ao.current));Pn(S,"scene.ri.zip"),W("Saved complete scene bundle."),J("success")}catch(l){W(l instanceof Error?l.message:"Could not save scene."),J("error")}finally{hn(!1)}}},Ol=async a=>{let l=a??Fo;if(Fr(null),!l)return;let{session:g,file:S}=l,{model:k}=g;Jn.current=null;let I=Mt.current,F=await Ru(li(Mo,g.sceneConfig));await Si(F.product);let H=await cn(g.bindings);if(await Mr(F),Mt.current!==I)return;let _=new Map,{parkedModels:ce,mergedModelSources:ne}=await Kg(l.parkedFiles,l.mergeFiles,_);if(Mt.current!==I){ce.forEach(xi),ne.forEach(Un);return}let Pe=ye=>{let at=new Map;at.set(Yt(k),ye),ce.forEach(Ft=>{Ft.sessionModel&&at.set(Yt(Ft.sessionModel),Ft.url)});let Lt=(g.modelOrder??[]).map(Ft=>at.get(Ft)).filter(Ft=>!!Ft),zl=new Set(Lt);for(let Ft of[ye,...ce.map(Zg=>Zg.url)])zl.has(Ft)||(Lt.push(Ft),zl.add(Ft));return Lt},ft=()=>{for(let[ye,at]of _)ao.current.set(ye,at),a?_i.current.delete(ye):_i.current.add(ye)},ke;if(k.kind==="file"){if(!S){ce.forEach(xi),ne.forEach(Un);return}let ye=Mt.current,at;try{at=await Po(S)}catch(Lt){console.warn("[BindingBuilder] Could not read the saved model:",Lt),W(Cs(k.name)),J("error"),ce.forEach(xi),ne.forEach(Un);return}if(Mt.current!==ye){at.cleanup(),ce.forEach(xi),ne.forEach(Un);return}Qe.current?.cleanup(),Qe.current=at,ke=at.url,_.set(k.key,S),ft(),Vr(),G.forEach(Lt=>Lt.resolved?.cleanup()),ee(ce),ho(ne),M(Pe(ke)),Ke.reset(g.composition?Wo(g.composition):qo),mn([])}else{ke=k.url,ft(),Vr(),G.forEach(at=>at.resolved?.cleanup()),ee(ce),ho(ne),M(Pe(ke)),Ke.reset(g.composition?Wo(g.composition):qo),mn([]);let ye=so.current;if(ke===y&&ye?.url===ke&&!rt.current){We.current={model:k},te.reset(ln(ye.scene,H,ne,vi(ye.scene,H).bindings)),Ne.reset(F),W(`Restored your last session with ${k.name}.`),J("success");return}Qe.current?.cleanup(),Qe.current=null}We.current={model:k,file:S??void 0},k.kind==="file"&&!a&&_i.current.add(k.key);let Dt=++Mt.current;ke!==y&&It.clearAnimations(),to(!0),Lo(null),So.current=0,Fe.current&&(clearTimeout(Fe.current),Fe.current=null),Vi.current=S?.size,W("Restoring your last session."),J("default"),Ce(k.name),X({url:ke,name:k.name}),yn(null),D(null),so.current=null,te.reset({}),Ne.reset(F),rt.current={requestId:Dt,modelName:k.name,modelUrl:ke,storedBindings:H,restoring:!0},Q(ke)};Le(()=>{let a=l=>{if((l.metaKey||l.ctrlKey)&&l.key.toLowerCase()==="k"){l.preventDefault(),Or(S=>!S);return}if(l.metaKey||l.ctrlKey||l.altKey||Hu(l.target,!0))return;if(l.key==="?"){l.preventDefault(),Er(S=>!S);return}if(!y)return;let g=fr.find(S=>S.shortcut.toLowerCase()===l.key.toLowerCase());g?(l.preventDefault(),zi(g.id)):l.key.toLowerCase()==="f"&&(l.preventDefault(),O?Sn(O):Qn())};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[y,O,Sn,Qn]);let kn=ap();if($o.status==="checking")return R("div",{className:"bb-root bb-root--licenseChecking",children:!x&&R(ma,{title:"Validating license key\u2026"})});if($o.status==="invalid")return R("div",{className:"bb-root bb-root--licenseInvalid",children:R(ma,{tone:"error",title:"Invalid license",showKeySetup:$o.isLocalDomain&&$o.reason==="No license key provided",message:$o.isLocalDomain?$o.reason??"License has been revoked or has expired":"Failed to load. Please contact the site administrator."})});let El=(Et==="annotations"||Tr.open&&Oi==="cinematic")&&Re?{position:Re.position,target:Re.target,azimuthAngle:Re.azimuthAngle,polarAngle:Re.polarAngle,fov:Re.fov,zoom:Re.zoom}:null,Yg=y?lo.get(y)??"Model":"Untitled scene",Go=Be&&!Lu.find(a=>a.id===Os)?.group?"general":Os,Jg=a=>{a.panel==="object"?(oo.setOpen(!0),un("object"),Es(a.tab)):a.panel==="scene"?(oo.setOpen(!0),un("scene"),Ir(a.tab)):a.panel==="configure"?(un("configure"),Gt("scene")):a.panel==="left"?(vo.setOpen(!0),Rr(a.tab)):(As(a.tab),Tr.setOpen(!0)),a.section&&wp(a.section)},Xg=()=>[...fr.map(a=>({id:`tool-${a.id}`,label:`${a.label} tool`,hint:"Tool",shortcut:a.shortcut,run:()=>zi(a.id)})),{id:"frame",label:"Frame selection",hint:"Camera",shortcut:"F",run:()=>{O?Sn(O):Qn()}},{id:"fit",label:"Fit scene",hint:"Camera",run:()=>{Qn()}},{id:"reset-view",label:"Reset view",hint:"Camera",run:()=>{Rl()}},{id:"code",label:"Show code",hint:"Code panel",keywords:"json typescript export",run:()=>{oo.setOpen(!0),Nr(!0)}},{id:"compare",label:"Compare before and after",hint:"Preview",run:()=>Xs(!0)},{id:"shortcuts",label:"Keyboard shortcuts",hint:"Help",shortcut:"?",run:()=>Er(!0)},...d?[{id:"add-model",label:"Add model",hint:"Model",keywords:"upload import asset",run:sa}]:[],...yp.map(a=>({id:`setting-${a.label}-${a.where.tab}`,label:a.label,hint:a.hint,keywords:a.keywords,run:()=>Jg(a.where)}))],jl=[{title:"Scene settings",description:"Lighting, camera, and environment for the active model. No model files or bindings.",onImport:vg,onExportJson:()=>Pl("json"),onExportTs:()=>Pl("ts"),importDisabled:!qt.length||Te,exportDisabled:!qt.length||Te},{title:"Object bindings",description:"Bindings for the active model, with uploaded textures when available. No model files or scene settings.",onImport:hg,onExportJson:()=>Ml("json"),onExportTs:()=>Ml("ts"),importDisabled:!qt.length||Te,exportDisabled:!qt.length||Te}],Il=d&&st(Uo,"sceneBundle")?{onImport:()=>Js.current?.click(),onExport:Wg,importDisabled:Te,exportDisabled:Te||!ve.length||ve.some(a=>!a.ready)}:void 0,ua=qe?R(it,{children:"Click the preview to look around \xB7 Esc to release"}):ro!=="select"&&!O?R(it,{children:"Select an object to transform it"}):ro==="move"?R(it,{children:"Drag an arrow or plane to move"}):ro==="rotate"?R(it,{children:"Drag a ring to rotate"}):ro==="scale"?R(it,{children:"Drag the handle to scale"}):wb&&Lr?se(it,{children:[se("span",{children:[R("kbd",{children:"W"}),R("kbd",{children:"A"}),R("kbd",{children:"S"}),R("kbd",{children:"D"})," move"]}),se("span",{children:["\xB7 ",R("kbd",{children:"Space"}),"/",R("kbd",{children:"C"})," up \xB7 down"]}),R("span",{children:"\xB7 drag to look"})]}):null;return se(cd.Provider,{value:Pb,children:[se("div",{className:"bb-root","data-input":"pointer",onPointerDownCapture:a=>{a.currentTarget.dataset.input="pointer"},onKeyDownCapture:a=>{a.key==="Tab"&&(a.currentTarget.dataset.input="keyboard")},onMouseOver:kn.onMouseOver,onContextMenu:kn.onContextMenu,onKeyDown:a=>{a.key!=="Escape"||a.defaultPrevented||!Be||a.target.closest('input:not([type="checkbox"]), textarea, select, [contenteditable="true"]')||(a.preventDefault(),a.stopPropagation(),$?ki():Ms())},children:[R("input",{ref:b,type:"file",accept:ga,className:"bb-hiddenInput",onChange:ng,disabled:Te}),R("input",{ref:N,type:"file",accept:ga,className:"bb-hiddenInput",onChange:lg,disabled:Te}),R("input",{ref:K,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:xg,disabled:Te}),R("input",{ref:T,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:yg,disabled:Te}),R("input",{ref:Js,type:"file",accept:".zip,application/zip",hidden:!0,onChange:async a=>{let l=a.target.files?.[0];a.target.value="",l&&await Al(l)}}),R(np,{modelName:Yg,modelMenu:d||ve.length>1?a=>R(ac,{close:a,models:ve.length>1?ve.map(l=>({url:l.url,label:lo.get(l.url)??l.name})):void 0,activeModelUrl:y,onSelectModel:Ko,onRestore:!d||y||u?void 0:_g,restoreDisabled:Te,onAddModel:d&&y?sa:void 0,onUpload:d&&!y?Cl:void 0,addModelDisabled:Te,onReset:d&&y?()=>Dg(qn):void 0,resetLabel:`Reset ${Fu[qn]} changes\u2026`,onRemove:d&&y&&(!u||Zn.length>1)?ig:void 0,confirmRemove:Zn.length<=1}):void 0,canUndo:_o.canUndo,canRedo:_o.canRedo,undoTarget:Fu[qn],onUndo:_o.undo,onRedo:_o.redo,tool:ro,onToolChange:a=>{zi(a),a!=="select"&&Gt("bindings")},space:Ws,onSpaceChange:gb,hasModel:!!y,compareOpen:Ho,onToggleCompare:()=>{Xs(a=>!a),Kr(null)},codeOpen:js,onToggleCode:()=>Nr(a=>!a),onOpenCommands:()=>Or(!0),start:e,xrToolsSlot:ob,fileActions:se(it,{children:[R(op,{scopes:jl,sceneBundle:Il,busy:fn||Bs}),R(tp,{scopes:jl,sceneBundle:Il,busy:fn||Bs})]})}),se("div",{className:`bb-workspace ${yo?"bb-workspace--customerPreview":""}`,children:[vo.open?se(it,{children:[se("aside",{className:"bb-panel bb-panel--left",style:{width:vo.size},onPointerDownCapture:()=>{Et==="assets"&&Gt("assets"),Et==="annotations"&&Gt("scene")},children:[se("div",{className:"bb-tabs",role:"tablist","aria-label":"Scene contents",children:[kv.filter(a=>a.id!=="assets"||d).map(a=>R("button",{type:"button",role:"tab","aria-selected":Et===a.id,className:`bb-tab ${Et===a.id?"bb-tab--active":""}`,onClick:()=>Rr(a.id),children:a.label},a.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:()=>vo.setOpen(!1),children:R(cv,{size:14})})]}),R("div",{className:`bb-panelBody ${Et==="outliner"?"bb-panelBody--fill":""}`,children:Et==="outliner"?R(Qp,{bindings:q,selectedItem:O,onSelect:da,onHover:Og,modelGroups:Vb,onSelectModel:Ko,isolatedItem:Pi,onIsolate:Kn,multiSelectEnabled:$,onToggleMultiSelect:Kt,onExitMultiSelect:ki,multiSelectedKeys:ue,onSetMultiSelected:Ng,hierarchy:Ob,selectionSets:oe.selectionSets,onSelectionSetsChange:mb,onRename:Fg,onSetVisible:Hg,onDelete:Nl,onFocus:Sn}):y?Et==="assets"?R(La,{assets:ve.map(a=>({...a,displayName:lo.get(a.url)})),activeUrl:y,composition:dt,busy:fn||Te,onFrameAll:()=>{let a=new zu;for(let g of ve){if(g.placement.visible===!1)continue;let S=Pt.current.get(g.url);S&&(S.updateWorldMatrix(!0,!0),a.union(new zu().setFromObject(S)))}let l=Vo.current;!a.isEmpty()&&l&&(wd(a,l.raw.controls),l.raw.controls.fitToBox(a,!0,Sd).then(()=>l.invalidate()))},onSelect:Ko,onAdd:sa,addRequiresTier:sl?void 0:Yo("models",ve.length),onChange:pa,onGridSize:a=>Ke.setValue(l=>({...l,gridSize:a})),onDuplicate:a=>{Gg(a)},onDelete:u?()=>gn(!0):qg,deleteIsPermanent:!!u,onSnap:a=>pa(a,Gl(dt.placements[a]??{},dt.gridSize)),onGround:a=>{let l=Pt.current.get(a),g=l?Wl(l):null;g&&pa(ko.get(a),ql(Xn(a),g))}}):Et==="annotations"?R(hv,{config:oe,onChange:jt,cameraState:El,onPreviewView:xl}):R("div",{ref:Ls,className:"bb-measurePanel"}):R("p",{className:"bb-panelEmpty",children:"Open a model to use this."})})]}),R(ui,{orientation:"vertical",label:"Resize left panel",onPointerDown:vo.startResize,onKeyDown:vo.onResizeKey})]}):R("button",{type:"button",className:"bb-panelReveal bb-panelReveal--left","aria-label":"Show left panel",title:"Show panel",onClick:()=>vo.setOpen(!0),children:R(pv,{size:14})}),se("main",{className:"bb-previewShell",children:[se("div",{className:"bb-preview",ref:A,onPointerDownCapture:a=>{Ci.current={shiftKey:a.shiftKey,ctrlKey:a.ctrlKey,metaKey:a.metaKey}},onKeyDownCapture:()=>{Ci.current={shiftKey:!1,ctrlKey:!1,metaKey:!1}},onFocus:a=>{a.currentTarget.contains(a.relatedTarget)||Jr()},children:[y?se("div",{className:"bb-viewportBar",children:[R(ai,{label:"View",icon:R(dv,{size:13,"aria-hidden":"true"}),title:"Preview options",children:()=>se(it,{children:[se("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Ks,onChange:a=>ab(a.target.checked)}),"Zoom on selected"]}),se("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Dr,onChange:a=>sb(a.target.checked)}),"Highlight on hover"]}),se("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Lr,onChange:a=>lb(a.target.checked)}),"Camera controls"]}),se("label",{className:"bb-headerMenuItem",children:[R("input",{type:"checkbox",checked:Ar,onChange:a=>Ju(a.target.checked)}),"Floor grid"]})]})}),se("label",{className:"bb-topBarSelect",title:"Renderer","data-ri-path":"sceneConfig.model.renderer",children:[R("span",{className:"bb-visuallyHidden",children:"Renderer"}),se("select",{value:oe.model.renderer,onChange:a=>jt({...oe,model:{...oe.model,renderer:a.target.value}}),children:[R("option",{value:"pbr",children:"PBR"}),R("option",{value:"matcap",children:"Matcap"}),R("option",{value:"uv-checker",children:"UV checker"})]}),R(rv,{size:12,"aria-hidden":"true"})]})]}):null,R(bd,{visible:Te,title:E||void 0,message:Pr,progress:Bb??void 0}),y&&R("div",{className:`bb-canvasHint ${ua?"bb-canvasHint--visible":""} ${Ho?"bb-canvasHint--belowCompare":""}`,"aria-hidden":!ua,children:ua}),yo?R("button",{type:"button",className:"bb-customerPreviewExit",onClick:()=>jr(!1),children:"Previewing as a customer \xB7 Exit"}):null,y?R(ya,{loading:"eager",enableXR:!0,arHandoff:n,mobileHandoffUrl:c,modelUrl:y,tilesetUrl:Ee?.tilesetUrl,models:_b,onModelChange:Ko,onExtraModelLoaded:fg,onExtraModelError:mg,mergeModels:oa,onMergeModelLoaded:bg,onMergeModelError:gg,originalNodePoses:Ct.current,objectBindings:q,comparisonHighlights:Zs?.after,selectedObject:Me,selectedObjectRefs:zb,selectedObjectOutlineColor:"#35c0dc",onObjectSelect:Ag,onSelectionClear:Ms,onObjectBindingsChange:Do,onTextureUpload:Wb,onObjectEditLeaseChange:(a,l)=>v?.(`${y}|${a.modelObjectId||a.id}`,l),showObjectBindingDataPanel:!1,showSceneObjectsPanel:!1,onCameraChange:Fb,onViewerReady:a=>{Vo.current=a,Ib(a.raw.nodes),Db(a)},onAnnotationsChange:Gb,activeAnnotation:Cb?.annotation??null,onActiveAnnotationChange:qb,onSequencesReady:jb,showSequenceControls:!1,sequenceAutoPlay:!1,onAnimationsReady:og,onModelAnimationsReady:zt.handleModelAnimationsReady,onSceneLoaded:Zb,onAssetDiagnostics:ea?a=>dl({url:y,report:a}):void 0,onRuntimeStats:ea?cl:void 0,onLoadError:eg,onObjectCatalog:Ee?.tilesetUrl?Qb:void 0,onProgress:tg,onCameraControllerChange:Wr,cameraControllerType:Qs,onTexturePositioningChange:Sb,endTexturePositioningRef:ol,licenseKey:i,licenseValidationUrl:r,dracoDecoderPath:s,ktx2TranscoderPath:p,meshopt:f,sceneConfig:$b,onSceneConfigChange:Ub,productOptions:yo?!0:void 0,preserveDrawingBuffer:!0,disableZoom:!1,zoomOnSelected:Ks,highlightOnHover:Dr,enableCameraControls:Lr,moveModeEnabled:ub,scaleModeEnabled:bb,gizmoTool:ro==="rotate"?"rotate":"move",showFloorGrid:Ar&&!yo,objectTransformSpace:Ws,enableKeyboardNavigation:!0,showViewGizmo:!yo,showMeasureTools:!0,measurementModelId:We.current?.model.kind==="file"?Yt(We.current.model):void 0,showSectionTools:!0,isolation:Uu,onIsolationChange:()=>Kn(null),showIsolateControls:!0,decalMove:Pg,onDecalDoubleClick:Rg,panelHoveredObject:Dr?Mb:null,showLoadingOverlay:!1,autoRotate:qe?!1:oe.model.autoRotate??!1,autoRotateSpeed:oe.model.autoRotateSpeed??1}):R("div",{className:`bb-previewPlaceholder ${Yu?"bb-previewPlaceholder--dragActive":""}`,onDragEnter:wg,onDragOver:Sg,onDragLeave:kg,onDrop:Cg,children:se("div",{className:"bb-dropCard",children:[R(iv,{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(a=>R("span",{children:a},a))}),d?R("button",{type:"button",className:"bb-button bb-button--primary",onClick:Cl,disabled:Te,children:"Choose file"}):null]})}),y&&Ho?R(dc,{showOutlines:_r,onShowOutlinesChange:vb,matchBy:Gr,onMatchByChange:a=>{yb(a),qr(null)},report:Yn??void 0,selected:Li,onSelect:a=>{qr(a?.id??null),a?.afterKey&&da(a.afterKey)},liveViewerRef:Vo,split:hb,onSplitChange:xb,labels:[xn?"Pinned":"Before","Now"],beforeAction:se("button",{type:"button",className:"ri-compare__labelAction",onClick:()=>Kr(a=>a?null:{bindings:q,sceneConfig:oe}),"aria-pressed":!!xn,title:xn?"Unpin: compare with the project as it was opened again":"Pin as before: compare later changes with how the preview looks now",children:[xn?R(mv,{size:12}):R(gv,{size:12}),xn?"Unpin":"Pin"]}),renderBefore:a=>R(ya,{loading:"eager",modelUrl:y,tilesetUrl:Ee?.tilesetUrl,comparisonHighlights:Zs?.before,objectBindings:vn.bindings,sceneConfig:{...vn.sceneConfig,section:oe.section},licenseKey:i,licenseValidationUrl:r,dracoDecoderPath:s,ktx2TranscoderPath:p,meshopt:f,preset:"minimal",showFloorGrid:Ar,showLoadingOverlay:!1,showObjectNavigator:!1,selectedObject:null,zoomOnSelected:!1,highlightOnHover:!1,autoRotate:!1,cinematic:!1,onViewerReady:a})}):null]}),R(Iu,{panel:Tr,tabs:Cv,tab:Oi,onTabChange:As,hasModel:!!y,onPointerDownCapture:()=>Gt("scene"),children:Oi==="sequences"?R(vv,{config:oe,onChange:jt,controls:Eb,bindings:q,clipDetails:It.clipDetails}):Oi==="clips"?R(xv,{config:Gi.config?{...oe,animations:Gi.config}:oe,onChange:Gi.onChange?a=>Gi.onChange?.(a.animations):jt,clipDetails:zt.clipDetails,active:zt.active,play:zt.play,pause:zt.pause,stop:zt.stop,setSpeed:zt.setSpeed,seek:zt.seek}):st(Uo,"cinematic")?R(yv,{config:oe,onChange:jt,cameraState:El,onPreviewWaypoint:xl}):R(Ye,{requiredTier:"starter",feature:"Cinematic"})})]}),oo.open?se(it,{children:[R(ui,{orientation:"vertical",label:"Resize inspector",onPointerDown:oo.startResize,onKeyDown:oo.onResizeKey}),se("aside",{className:"bb-panel bb-panel--right",style:{width:oo.size},onPointerDownCapture:()=>Gt(kt!=="object"?"scene":"bindings"),children:[se("div",{className:"bb-inspectorScope",children:[R("div",{className:"bb-scopeSwitch",role:"tablist","aria-label":"What to edit",children:["object","scene","configure"].map(a=>R("button",{type:"button",role:"tab","aria-selected":kt===a,className:kt===a?"is-active":"",onClick:()=>{un(a),Gt(a==="object"?"bindings":"scene")},children:a==="object"?"Object":a==="scene"?"Scene":"Configure"},a))}),R("button",{type:"button",className:"bb-toolButton bb-toolButton--small","aria-label":"Hide inspector",title:"Hide panel",onClick:()=>oo.setOpen(!1),children:R(uv,{size:14})})]}),kt==="configure"?y?R("section",{className:"bb-editor",children:R(wv,{config:oe,onChange:Ne.setValueAsStep,objectBindings:q,materialVariantGroups:pl,selectedKey:O,previewSelections:Ei,onPreviewChange:zs,onPreviewAsCustomer:()=>jr(!0),publish:o,modelFileName:E})}):R("p",{className:"bb-panelEmpty",children:"Open a model to let customers customise it."}):kt==="scene"?y?se(it,{children:[R("div",{className:"bb-tabs",role:"tablist","aria-label":"Scene settings",children:qc.map(a=>R("button",{type:"button",role:"tab","aria-selected":bn===a.id,className:`bb-tab ${bn===a.id?"bb-tab--active":""}`,onClick:()=>Ir(a.id),children:a.label},a.id))}),R("section",{className:"bb-editor",children:R(Da,{diagnostics:{report:ll?.url===y?ll.report:null,runtimeStats:Nb,onRefresh:Ab,onSelectObject:a=>{let l=Object.keys(q).find(g=>g===a||q[g].modelObjectId===a);l&&da(l)}},onDiagnosticsOpenChange:Rb,config:oe,onChange:jt,activeSubTab:bn,materialVariantGroups:pl,onImageFile:Tl,objectBindings:q})})]}):R("p",{className:"bb-panelEmpty",children:"Open a model to edit its scene."}):!Me||!O?R("p",{className:"bb-panelEmpty",children:y?"Select an object to edit it.":"Open a model, then select an object to edit it."}):se(it,{children:[se("div",{className:"bb-objectHeader",children:[se("div",{className:"bb-objectHeaderText",children:[R("h2",{children:Be&&ue.length>1?`${ue.length} objects`:Me.label||O}),R("code",{title:Be?void 0:Me.modelObjectId,children:Be&&ue.length>1?"Edits apply to all of them":Me.id})]}),R(ai,{icon:R(lv,{size:14,"aria-hidden":"true"}),title:"Object actions",align:"right",children:a=>se(it,{children:[se("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>{a(),$u({name:Me.label||O,style:Ad(Me)})},children:[R(sv,{size:13,"aria-hidden":"true"}),"Copy style"]}),se("button",{type:"button",className:"bb-headerMenuItem",disabled:!_n,title:_n?`Copied from ${_n.name}`:void 0,onClick:()=>{if(a(),!_n)return;let l=Be?ue:[O];te.setValueAsStep(g=>Od(g,l,_n.style))},children:[R(av,{size:13,"aria-hidden":"true"}),"Paste style",Be&&ue.length>1?` to ${ue.length}`:""]}),se("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{a(),Nl(Be&&ue.length>0?ue:[O])},children:[R(fv,{size:13,"aria-hidden":"true"}),Be&&ue.length>1?`Delete ${ue.length} objects\u2026`:"Delete object\u2026"]})]})})]}),R("div",{className:"bb-tabs",role:"tablist","aria-label":"Object settings",children:Lu.filter(a=>!Be||a.group).map(a=>R("button",{type:"button",role:"tab","aria-selected":Go===a.id,className:`bb-tab ${Go===a.id?"bb-tab--active":""}`,onClick:()=>Es(a.id),children:a.label},a.id))}),se("section",{className:"bb-editor",children:[Go==="general"&&se(it,{children:[!Be&&R(Rp,{selectedItem:O,selectedBinding:Me,open:no.identity,onToggle:()=>io("identity"),updateBinding:Bt,idError:Yb}),!Be&&R(Ap,{selectedItem:O,selectedBinding:Me,open:no.basics,onToggle:()=>io("basics"),updateBinding:Bt}),Be&&R(Je,{title:"Basics",open:no.basics,onToggle:()=>io("basics"),children:R("div",{className:"bb-groupFlags",children:["selectable","hoverable","visible"].map(a=>R(Sv,{label:a.charAt(0).toUpperCase()+a.slice(1),values:ue.map(l=>q[l]).filter(l=>l&&!l.removed).map(l=>l[a]!==!1),onChange:l=>te.setValueAsStep(g=>{let S={...g};for(let k of ue)g[k]&&!g[k].removed&&(S[k]={...g[k],[a]:l});return S})},a))})}),R(Up,{selectedItem:O,selectedBinding:Me,open:no.transform,onToggle:()=>io("transform"),updateBinding:Bt,originalTransform:Ct.current[O]??null,originalTransforms:Ct.current}),!Be&&R(Lp,{selectedBinding:Me,open:no.camera,onToggle:()=>io("camera"),cameraState:Re,formattedCameraState:Kb,savedCameraPosition:Co,onSaveCameraPosition:Eg,onGoToSavedCamera:jg,onClearSavedCamera:Ig,onResetView:Rl,onFitScene:Qn})]}),Go==="material"&&se("div",{className:"bb-singleSection",children:[R(Tp,{disabled:!O,onApply:a=>O&&ia(O,l=>({...l,...a}))}),R(Pp,{selectedItem:O,selectedMaterial:ta,pbrWorkflow:nb,onPbrWorkflowChange:ib,openMaterialPanels:Qu,materialPanelEnabled:rb,onToggleMaterialPanel:tb,onSetMaterialPanelState:Xb,updateSelectedMaterial:ia,setSelectedTexturePath:Jb,isTexturePositioningEnabled:kb,onConfirmTexturePosition:zg,takesImage:yl})]}),Go==="decals"&&R("div",{className:"bb-singleSection",children:!Be&&R(Dp,{selectedItem:O,selectedBinding:Me,open:no.decals,onToggle:()=>io("decals"),updateBinding:Bt,placement:Bi,onPlacementChange:Tg,defaultSize:Mg,onImageFile:Tl,onNudge:Bg})}),Go==="actions"&&R("div",{className:"bb-singleSection",children:!Be&&R(Ep,{selectedItem:O,selectedBinding:Me,open:no.actions,onToggle:()=>io("actions"),updateBinding:Bt,takesImage:yl})}),Go==="data"&&se(it,{children:[R(rs,{title:"Metrics",label:"Metrics JSON",open:no.metrics,onToggle:()=>io("metrics"),draft:Rs,error:qu,example:'{"area": 42}',onDraftChange:Ti,onCommit:()=>Bl("metrics",Rs,Ni)}),R(rs,{title:"Metadata",label:"Metadata JSON",open:no.metadata,onToggle:()=>io("metadata"),draft:Ns,error:Wu,example:'{"room": "kitchen"}',onDraftChange:Ri,onCommit:()=>Bl("metadata",Ns,Ai)})]})]})]}),js?R(mp,{scope:kt==="object"?"object":"scene",selectedKey:O,selectedBinding:Me??null,sceneConfig:oe,sceneTab:kt==="configure"?"product":bn,onClose:()=>Nr(!1)}):null]})]}):R("button",{type:"button",className:"bb-panelReveal bb-panelReveal--right","aria-label":"Show inspector",title:"Show panel",onClick:()=>oo.setOpen(!0),children:R(bv,{size:14})})]}),R(lp,{saveState:Wi&&y?"Saved in this browser":void 0,objectCount:qt.filter(a=>!q[a]?.removed).length,selectedCount:Be?ue.length:O?1:0,path:kn.path,hints:Mv}),R(pp,{toast:Ku,onDismiss:Gu}),kn.menu?R(sp,{...kn.menu,onClose:kn.closeMenu}):null,Xu?R(xp,{commands:Xg(),onClose:()=>Or(!1)}):null,Zu?R(vp,{onClose:()=>Er(!1)}):null]}),db&&R(wu,{target:Wn,onCancel:Ji,onConfirm:Lg}),Fo&&R(Su,{models:[{name:Fo.session.model.name,mergedCount:Fo.session.mergeModels?.length??0},...(Fo.session.parkedModels??[]).map(a=>({name:a.model.name,mergedCount:a.mergeModels?.length??0}))],savedAt:Fo.session.savedAt,onCancel:Vg,onConfirm:()=>{let{name:a}=Fo.session.model;Ol().catch(l=>{console.warn("[BindingBuilder] Could not restore the session:",l),W(Cs(a)),J("error")})}}),cb&&R(Cu,{destinations:Zn.filter(a=>a.kind==="model"),onCancel:dg,onChoose:cg}),pb&&R(Mu,{options:Zn,onCancel:rg,onRemoveModel:ag,onRemoveMerge:sg,permanent:!!u,onRemoveAll:u?void 0:()=>{gn(!1),Yi()}}),wo&&R(ku,{nodeLabel:wo.length===1?q[wo[0]]?.label||wo[0]:`${wo.length} objects`,count:wo.length,onCancel:$g,onConfirm:Ug})]})}export{dr as a,Vv as b,Pv as c};