@displayxr/inline3d 1.34.0 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/camera.d.ts +23 -0
- package/dist/call.js +4 -4
- package/js/inline3d-call.js +25 -2
- package/js/inline3d-camera.js +105 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ entry points (`.`, `./three`) are frozen for 1.x, while the **scene subpaths** (
|
|
|
5
5
|
`./splat`, `./model`) are a preview tier whose options may change in any release. Entries below say
|
|
6
6
|
which tier they touch, because that is what tells you whether an upgrade can move your pixels.
|
|
7
7
|
|
|
8
|
+
## 1.35.0 — 2026-10-06
|
|
9
|
+
|
|
10
|
+
Touches the **preview tier** (`./camera`, `./call`) additively. The core is unchanged (one new
|
|
11
|
+
unit test pins its existing behaviour).
|
|
12
|
+
|
|
13
|
+
### `./call` + `./camera` — the self view never shows a squeezed pair (web#131)
|
|
14
|
+
|
|
15
|
+
- **The self view follows its tile's `firstWoven`.** Seen once in the DisplayXR Browser: a
|
|
16
|
+
call's self view showed the whole packed L|R pair in each eye under a `You · 3D` badge, the
|
|
17
|
+
look of a canvas the browser is not weaving. `addCameraView` now watches `handle.firstWoven`
|
|
18
|
+
the way a remote tile does: on `woven: false` (`'layer-failed'`, `'session-ended'`) the view
|
|
19
|
+
drops to `'flat-left'` (one eye, mirrored), re-registers a refused layer up to 4 times with
|
|
20
|
+
backoff, and re-weaves on `_reroute(true, wall)` when a wall comes back.
|
|
21
|
+
- **The self badge is honest**: `3D` only while the view is on the woven route.
|
|
22
|
+
- **`CameraView` additions**: `fallbackReason`, `weaveState()` and the `onRouteChange` option
|
|
23
|
+
(types: `CameraViewWeaveState` in `camera.d.ts`).
|
|
24
|
+
- **`call.diagnostics().self`** = `{ route, woven, reason, firstWoven, layerRetries }`, so the
|
|
25
|
+
next occurrence can be diagnosed from devtools.
|
|
26
|
+
- Hardening, not a root-cause fix: `firstWoven` is the SDK's hold timer, so a layer the browser
|
|
27
|
+
silently never joins still reads as woven.
|
|
28
|
+
|
|
8
29
|
## 1.34.0 — 2026-10-06
|
|
9
30
|
|
|
10
31
|
### `./model` — the PlayCanvas drag is a turntable again
|
package/camera.d.ts
CHANGED
|
@@ -193,6 +193,24 @@ export interface CameraViewOptions {
|
|
|
193
193
|
depth?: number;
|
|
194
194
|
/** The tile's aspect (w/h) = the woven buffer's per-eye aspect. Default 16/9. */
|
|
195
195
|
aspect?: number;
|
|
196
|
+
/**
|
|
197
|
+
* Called when the view's route changes — including when the wall says the tile will not weave
|
|
198
|
+
* and the view drops to its flat left eye by itself — and when its `firstWoven` settles. Keep a
|
|
199
|
+
* "3D" badge on `view.woven`, not on the wall.
|
|
200
|
+
*/
|
|
201
|
+
onRouteChange?: (route: CameraView['route'], state: CameraViewWeaveState) => void;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** What a {@link CameraView} actually shows (`view.weaveState()`), for diagnostics. */
|
|
205
|
+
export interface CameraViewWeaveState {
|
|
206
|
+
route: 'woven-sbs' | 'flat-left' | 'flat' | null;
|
|
207
|
+
woven: boolean;
|
|
208
|
+
/** Why a pair on a 3D wall is flat: the tile's `firstWoven` reason (`'layer-failed'`, `'session-ended'`), else null. */
|
|
209
|
+
reason: string | null;
|
|
210
|
+
/** The current registration's settled `firstWoven`, `'pending'`, or null off the woven route. */
|
|
211
|
+
firstWoven: { woven: boolean; confirmed: boolean; reason: string | null; ms: number } | 'pending' | null;
|
|
212
|
+
/** Layer re-registrations attempted after a `'layer-failed'` (bounded; reset by a woven result). */
|
|
213
|
+
layerRetries: number;
|
|
196
214
|
}
|
|
197
215
|
|
|
198
216
|
/** A self view from {@link addCameraView}. */
|
|
@@ -200,7 +218,12 @@ export interface CameraView {
|
|
|
200
218
|
readonly canvas: HTMLCanvasElement;
|
|
201
219
|
/** `'woven-sbs'`: 3D on the panel; `'flat-left'`: a pair shown as its left eye; `'flat'`: mono. */
|
|
202
220
|
readonly route: 'woven-sbs' | 'flat-left' | 'flat' | null;
|
|
221
|
+
/** On the woven route. A tile the wall will not weave drops the view flat, so this goes false with it. */
|
|
203
222
|
readonly woven: boolean;
|
|
223
|
+
/** Why a pair on a 3D wall is shown flat (`'layer-failed'`, `'session-ended'`), else null. */
|
|
224
|
+
readonly fallbackReason: string | null;
|
|
225
|
+
/** What the view actually shows, for diagnostics. */
|
|
226
|
+
weaveState(): CameraViewWeaveState;
|
|
204
227
|
/** The wall's tile handle while woven (its `firstWoven` settles when the tile is safe to reveal), else null. */
|
|
205
228
|
readonly handle: TileHandle | null;
|
|
206
229
|
readonly mirror: boolean;
|
package/dist/call.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/* @displayxr/inline3d 1.
|
|
2
|
-
var _e=Object.freeze({speaker:"high",other:"normal",hidden:"paused"}),Cn=["high","normal","low","paused"],Rn=.02,Dn=1e3/20,Ln=3e3,An=1e3/28;function ye(n){return typeof n=="function"?n:n===!1||n==="off"?"off":"auto"}function it(n=import.meta.url){return ge?typeof ge=="function"?ge():ge:new URL("../lift/index.js",n).href}var ge=null;function ii(n){ge=n||null}function In(){return import(it())}async function nt(n,{importer:e=In,nav:t=globalThis.navigator,log:i=null,capsOpts:r={webFallback:!0}}={}){let s=(h,d)=>i&&i(h,d),o=(h,d={})=>(s("lift-unavailable",{reason:h,...d}),{lift:null,capabilities:null,caps:null,source:"none",reason:h}),a=ye(n);if(a==="off")return{lift:null,capabilities:null,caps:null,source:"none",reason:"off"};if(typeof a=="function"){let h=typeof a.liftCapabilities=="function"?a.liftCapabilities:null;return{lift:a,capabilities:h,caps:null,source:"injected",reason:null}}let l;try{l=await e()}catch(h){return o("import-failed",{message:String(h&&h.message||h).slice(0,200)})}let c=l&&typeof l.lift=="function"?l.lift:null;if(!c)return o("no-lift-export");let p=typeof l.liftCapabilities=="function"?l.liftCapabilities:null,f=null;if(p){try{f=await p(r)}catch{f=null}let h=!!(f&&f.webFallback&&f.webFallback.webgpu);if(f&&!f.native&&!h)return o("no-provider",{native:!1,webgpu:!1})}else if(!(t&&t.gpu))return o("no-webgpu");return s("lift-ready",{native:!!(f&&f.native),provider:f&&f.provider||null}),{lift:c,capabilities:p,caps:f,source:"module",reason:null}}function ve(n){let e=Number.isFinite(+n)&&n!==null?Math.max(-1,Math.min(1,+n)):0;return Math.abs(e)<Rn?"auto":Math.round((.5+.5*e)*1e3)/1e3}function Le({id:n,speakerId:e,visible:t=!0}){return t?n!=null&&n===e?_e.speaker:_e.other:_e.hidden}function rt(n,e){if(!n||!Cn.includes(e)||typeof n.setPriority!="function")return!1;try{return n.setPriority(e)!==!1}catch{return!1}}function st({degradedMs:n=Dn,recoveredMs:e=An,holdMs:t=Ln,alpha:i=.1}={}){let r=null,s=0,o=!1;return{feed(a){if(!(a>0)||a>1e3)return null;if(r=r===null?a:r+i*(a-r),o){if(r<e)return o=!1,s=0,"recovered"}else if(s=r>n?s+a:0,s>=t)return o=!0,"degraded";return null},reset(){r=null,s=0,o=!1},get frameMs(){return r},get degraded(){return o}}}function ot({lift:n,max:e=4,log:t=null,options:i=null}={}){let r=i&&typeof i=="object"?i:{},s=new Map,o=null,a=0,l=0,c=(h,d)=>t&&t(h,d),p=(h,d)=>{if(!d.handle)return;let m=Le({id:h,speakerId:o,visible:d.visible});if(m===d.priority)return;d.priority=m;let u=rt(d.handle,m);c("lift-priority",{peer:h,priority:m,applied:u})},f={get size(){return s.size},get max(){return e},set max(h){e=Math.max(0,h|0)},has:h=>s.has(h),handle:h=>s.get(h)&&s.get(h).handle||null,priority:h=>s.get(h)&&s.get(h).priority||null,canAcquire:h=>s.has(h)||s.size<e,acquire(h,d,{wall:m,visible:u=!0,onError:v}={}){let y=s.get(h);if(y)return y.pending||Promise.resolve(y.handle);if(s.size>=e)return Promise.resolve(null);let b=++l,C=Le({id:h,speakerId:o,visible:u}),x={gen:b,handle:null,visible:u,priority:C,pending:null};s.set(h,x);let O={quality:"auto",...r,mode:"live",wall:m,ui:"none",convergence:ve(a),priority:C};return c("lift-acquire",{peer:h,priority:C,convergence:O.convergence}),x.pending=Promise.resolve().then(()=>n(d,O)).then(T=>{if(s.get(h)!==x||x.gen!==b){try{T&&T.remove&&T.remove()}catch{}return null}return x.pending=null,x.handle=T||null,x.priority=null,p(h,x),T&&typeof T.setConvergence=="function"&&T.setConvergence(ve(a)),x.handle},T=>(s.get(h)===x&&s.delete(h),c("lift-failed",{peer:h,message:String(T&&T.message||T).slice(0,200)}),v&&v(T),null)),x.pending},release(h){let d=s.get(h);if(d){if(s.delete(h),d.handle)try{d.handle.remove()}catch{}c("lift-release",{peer:h})}},releaseAll(){for(let h of[...s.keys()])f.release(h)},setSpeaker(h){o=h===void 0?null:h;for(let[d,m]of s)p(d,m)},setVisible(h,d){let m=s.get(h);!m||m.visible===!!d||(m.visible=!!d,p(h,m))},setDepth(h){a=h;let d=ve(h);for(let m of s.values())m.handle&&typeof m.handle.setConvergence=="function"&&m.handle.setConvergence(d);return d},get anyWeb(){for(let h of s.values())if(h.handle&&!h.handle.native)return!0;return!1},list(){return[...s].map(([h,d])=>({id:h,priority:d.priority,pending:!!d.pending,native:!!(d.handle&&d.handle.native)}))}};return f}var Pn=null;function ni(n){Pn=typeof n=="function"?n:null}var Fn=new WeakMap;function ri(n,e){n&&(typeof n=="object"||typeof n=="function")&&Fn.set(n,e)}var jn=Object.freeze({displaySizeM:Object.freeze([.3456,.1944]),displayPixels:Object.freeze([1920,1080]),nominalViewerM:.65,eyeSeparationM:.063});function si(n,e,t=1){let i=jn,r=!!n&&n.displayWidthMeters>0&&n.displayHeightMeters>0&&n.displayPixelWidth>0&&n.displayPixelHeight>0,s=r?[n.displayWidthMeters,n.displayHeightMeters]:[...i.displaySizeM],o=r?[n.displayPixelWidth,n.displayPixelHeight]:[...i.displayPixels],a=(s[0]/o[0]+s[1]/o[1])/2,l=t>0?t:1,c=r?a*l:a*(o[1]/Math.max(1,globalThis.innerHeight||o[1])),p=n?.nominalViewerPosition?.z,f=Number.isFinite(p)&&p>.1;return{canvasSizeM:[(e?.width||0)*c,(e?.height||0)*c],metersPerCssPx:c,displaySizeM:s,nominalViewerM:f?p:i.nominalViewerM,eyeSeparationM:i.eyeSeparationM,source:{size:r?"display":"default",viewer:f?"display":"default",eyeSeparation:"default"}}}var oi=new WeakMap,J;function ai(n){let e=null;for(let[t,i]of n)i>0&&(!e||i<e[1])&&(e=[t,i]);return e}function Wn(n){if(!n||typeof n.getParameter!="function")return null;let e=oi.get(n);if(e)return e;let t,i,r;try{t=n.getParameter(n.MAX_TEXTURE_SIZE??3379),i=n.getParameter(n.MAX_RENDERBUFFER_SIZE??34024),r=n.getParameter(n.MAX_VIEWPORT_DIMS??3386)}catch{return null}let s=r&&r.length>=2?r[0]:0,o=r&&r.length>=2?r[1]:0,a=ai([["MAX_TEXTURE_SIZE",t],["MAX_RENDERBUFFER_SIZE",i],["MAX_VIEWPORT_DIMS",s]]),l=ai([["MAX_TEXTURE_SIZE",t],["MAX_RENDERBUFFER_SIZE",i],["MAX_VIEWPORT_DIMS",o]]);if(!a||!l)return null;let c={maxW:a[1],maxH:l[1],nameW:a[0],nameH:l[0],valueW:a[1],valueH:l[1]};return oi.set(n,c),c}function li(){if(J!==void 0)return J;J=null;try{if(typeof document>"u"||!document||typeof document.createElement!="function")return J;let n=document.createElement("canvas"),e=n.getContext("webgl2")||n.getContext("webgl");if(!e)return J;J=Wn(e),e.getExtension?.("WEBGL_lose_context")?.loseContext?.()}catch{J=null}return J}function ci(n,e,t,{cols:i=2,rows:r=1}={}){let s=n*i,o=e*r,a={eyeW:n,eyeH:e,cols:i,scale:1,clamped:!1,reqW:s,reqH:o,bufW:s,bufH:o,limitName:"",limitValue:0};if(!t||!(n>0)||!(e>0))return a;let l=t.maxW/s,c=t.maxH/o,p=Math.min(l,c);if(!(p<1))return a;let f=l<=c,h=Math.max(1,Math.min(Math.floor(n*p+1e-9),Math.floor(t.maxW/i))),d=Math.max(1,Math.min(Math.floor(e*p+1e-9),Math.floor(t.maxH/r)));return{eyeW:h,eyeH:d,cols:i,scale:p,clamped:!0,reqW:s,reqH:o,bufW:h*i,bufH:d*r,limitName:f?t.nameW:t.nameH,limitValue:f?t.valueW:t.valueH}}function at(n){return Math.round(n*1e3)/1e3}function di(n,e,t){let i=typeof t=="number"?` (renderScale ${at(t)} \u2192 ${at(t*e.scale)})`:` (scale ${at(e.scale)})`;return`${n} ${e.cols===1?"buffer":"SBS buffer"} ${e.reqW}\xD7${e.reqH} exceeds ${e.limitName} ${e.limitValue} on this device; rendering at ${e.bufW}\xD7${e.bufH}${i}.`}function hi(n,e){let t=n?.width||0,i=n?.height||0,r=e&&e.drawingBufferWidth>0?e.drawingBufferWidth:t,s=e&&e.drawingBufferHeight>0?e.drawingBufferHeight:i,o=t>0?r/t:1,a=i>0?s/i:1;return{sx:o,sy:a,w:r,h:s,mismatch:o!==1||a!==1}}function fi(n,e,t,i="laying the eyes out from the drawing buffer. Lower renderScale to stay inside the device limit."){return`${n} the browser clamped this canvas's drawing buffer to ${t.w}\xD7${t.h} (canvas.width/height say ${e.width}\xD7${e.height}); ${i}`}var ie="smoothstep",ct=["linear","smoothstep","easeoutcubic"];function dt(n){if(typeof n!="string")return null;let e=n.toLowerCase().replace(/[-_\s]/g,"");return ct.includes(e)?e:null}function Nn(n,e){if(e<=0)return 0;if(e>=1)return 1;if(n==="linear")return e;if(n==="easeoutcubic"){let t=1-e;return 1-t*t*t}return e*e*(3-2*e)}var te="idle",ui="rampDownThenFire",lt="fireThenRampUp",Ae=class{constructor(e,t){this._phase=te,this._targetMode=null,this._firePending=!1,this._fireAtEnd=!1,this._from=0,this._to=0,this._cur=0,this._t=1,this._dur=180/1e3,this._easing=ie,(e!==void 0||t!==void 0)&&this.configure(e,t)}configure(e,t){if(e!==void 0){let i=Number(e);this._dur=Number.isFinite(i)&&i>0?i:0}return t!==void 0&&(this._easing=dt(t)||ie),this}get durationS(){return this._dur}get easing(){return this._easing}request({targetMode:e=null,targetViewCount:t,currentMode:i=null,currentViewCount:r,current:s,steady:o=1}={}){let a=!(t>1),l=!(r>1),c=Number.isFinite(o)?o:1,p=Number.isFinite(s)?s:c;return this._targetMode=e,this._from=p,a&&!l?(this._phase=ui,this._to=0,this._fireAtEnd=!0,this._firePending=!1):!a&&l?(this._phase=lt,this._from=0,this._to=c,this._firePending=!0,this._fireAtEnd=!1):(this._phase=lt,this._to=a?p:c,this._firePending=!(e!==null&&e===i),this._fireAtEnd=!1),this._t=this._dur>0?0:1,this._cur=this._from,this}update(e){let t=!1;if(this._phase!==te){let i=Number.isFinite(e)&&e>0?e:0;this._t<1&&this._dur>0?(this._t+=i/this._dur,this._t>1&&(this._t=1)):this._t=1,this._cur=this._from+(this._to-this._from)*Nn(this._easing,this._t),this._phase===lt?(this._firePending&&(this._firePending=!1,t=!0),this._t>=1&&(this._phase=te)):this._t>=1&&(this._fireAtEnd&&(this._fireAtEnd=!1,t=!0),this._phase=te)}return{factor:this._cur,fire:t,mode:this._targetMode}}active(){return this._phase!==te}value(){return this._cur}firePending(){return this._phase===ui?this._fireAtEnd:this._firePending}cancel(){return this._phase=te,this._firePending=!1,this._fireAtEnd=!1,this._t=1,this}};var U=null;ni(n=>{let e=U;if(!e||!e._running||!n)return null;let t=i=>({layer:i.layer,session:e.session});for(let i of e._windows.values())if(i.canvas===n&&i.layer)return t(i);for(let i of e._windows.values())if(i.layer&&typeof n.contains=="function"&&n.contains(i.canvas))return t(i);for(let i of e._windows.values()){let r=i.canvas.parentElement;if(i.layer&&r&&typeof r.contains=="function"&&r.contains(n))return t(i)}return null});var zn=()=>typeof navigator<"u"&&!!navigator.xr,Q=()=>typeof window<"u"&&typeof window.XRDisplayLayer=="function",Ie=()=>Q()&&"excludeElement"in window.XRDisplayLayer.prototype,ht=()=>{if(!Q())return!1;try{return"setViewRig"in window.XRDisplayLayer.prototype}catch{return!1}},Hn=["getDisplayInfo","getRenderingModes","requestRenderingMode"],Si=["renderingmodechange","hardwaredisplaystatechange"],gt="trackingstatechange",Mi=["unknown","tracking","searching"],mi=[...Si,gt];function Oe(n){try{let e=n?n.trackingState:void 0;return Mi.includes(e)?e:null}catch{return null}}var ft=()=>{if(!Q())return!1;try{let n=window.XRDisplayLayer.prototype;return Hn.every(e=>typeof n[e]=="function")}catch{return!1}},ut=()=>{if(!Q())return!1;try{return typeof window.XRDisplayLayer.prototype.undock=="function"}catch{return!1}},re=null;function ne(){if(re!==null)return re;if(!Q())return!1;try{let n=window.XRDisplayLayer.occlusionByDrawOrder;if(typeof n=="boolean")return re=n}catch{}return!1}function Vn(n){if(re!==null)return re;if(!n||!Q()||!("occlusionByDrawOrder"in window.XRDisplayLayer.prototype))return null;try{return re=!!n.occlusionByDrawOrder}catch{return null}}var gi=!1;function pt(){gi||(gi=!0,console.info("[inline3d] This browser composites 2D over woven 3D automatically, per-pixel by draw order \u2014 overlay exclusion is obsolete here, so exclude()/addGlobalOverlay()/data-inline3d-overlay/autoChrome are accepted and ignored. Your 2D chrome already occludes the tiles correctly. The calls are harmless (keep them if you also ship to older DisplayXR Browsers); gate on inline3dOcclusionByDrawOrder() to drop them."))}function Ei(){return zn()&&Q()}function mt(n){return{type:"display",position:{x:0,y:0,z:0},orientation:{x:0,y:0,z:0,w:1},virtualDisplayHeight:n.virtualDisplayHeight>0?n.virtualDisplayHeight:.24,ipdFactor:1,parallaxFactor:1,perspectiveFactor:1}}function $n(n,e){let t=Number.isFinite(n.ipdFactor)?n.ipdFactor:1,i=Number.isFinite(n.parallaxFactor)?n.parallaxFactor:1;return{...n,ipdFactor:t*e,parallaxFactor:i*e}}var Un=16;function V(){return typeof performance<"u"&&performance&&typeof performance.now=="function"?performance.now():Date.now()}var Bn=1200,_i=!1;function qn(n){if(n==null)return ie;let e=dt(n);return e||(_i||(_i=!0,console.warn(`[inline3d] createInline3D({ modeSwitch: { easing: ${JSON.stringify(n)} } }) is not a curve this SDK knows (${ct.join(" / ")}); using '${ie}'.`)),ie)}var vi=!1;function Xn(){vi||(vi=!0,console.info("[inline3d] The active rendering mode is 1-view, so this SDK has zeroed every window rig (ipdFactor/parallaxFactor -> 0) \u2014 both eyes now render from one place. The runtime keeps weaving the same two-view atlas whatever the page submits, so leaving stereo in it would put two slightly different images on a flat panel, i.e. a blurry double image instead of 2D. Your rendering is unchanged; the flattening is a copy applied on the way to the layer and it is undone the moment a 2-view mode goes active again."))}function _t(n){return n&&n.detail!==void 0&&n.detail!==null?n.detail:void 0}function ki(n){let e=_t(n);return e!==void 0?[e,n]:[n]}function Gn(n){for(let e of ki(n)){if(typeof e=="number"&&Number.isFinite(e))return e;if(e&&typeof e=="object"){let t=e.modeIndex!==void 0?e.modeIndex:e.mode;if(typeof t=="number"&&Number.isFinite(t))return t}}return-1}function Jn(n){for(let e of ki(n)){if(e==="2d"||e==="3d")return e;if(e&&typeof e=="object"){let t=e.state!==void 0?e.state:e.hardwareDisplayState;if(t==="2d"||t==="3d")return t}}return null}var yi=!1;function Kn(){yi||(yi=!0,console.warn("[inline3d] This browser has no XRDisplayLayer.setViewRig, so the view rig was ignored (the window still weaves \u2014 the runtime keeps the default display rig, scaled by virtualDisplayHeight). Gate on inline3dViewRigSupported() if your page's framing depends on the rig; further calls are silent."))}var wi=!1;function Yn(){wi||(wi=!0,console.warn("[inline3d] addScene got BOTH viewRig and virtualDisplayHeight; on a browser with rig support the rig wins and the height is dropped. They describe the same slot \u2014 virtualDisplayHeight is shorthand for exactly one rig (display, identity pose, all factors 1) \u2014 so there is no merge. This is only worth passing as a PAIR deliberately: the height is what a browser without setViewRig will use, so a camera-rig scene can name its own fallback framing. Otherwise say it once, inside the rig."))}async function Ti(n={}){let{referenceSpace:e="viewer",lazy:t=!0,rootMargin:i="50% 0px",autoChrome:r=!0,modeSwitch:s=null,untrackedFallback:o="none",viewerEase:a}=n;if(!Ei())return{supported:!1,trackingState:"unknown"};let l;try{l=await navigator.xr.requestSession("inline-3d")}catch(p){return{supported:!1,trackingState:"unknown",error:p}}a!==void 0&&ri(l,a);let c=null;try{c=await l.requestReferenceSpace(e)}catch{}return new vt(l,c,{lazy:t,rootMargin:i,autoChrome:r,modeSwitch:s,untrackedFallback:o})}var we=null;function Fe(n={}){return U&&U._running?Promise.resolve(U):we||(we=Ti(n).finally(()=>{we=null}),we)}var bi=.7,Zn=new Set(["IMG","SVG","VIDEO","CANVAS","BUTTON","INPUT","SELECT","TEXTAREA"]);function Qn(n){let e=[],t=document.createTreeWalker(n,NodeFilter.SHOW_ELEMENT);for(let i=t.nextNode();i;i=t.nextNode())if(!i.closest("[data-inline3d-no-overlay]")){if(Zn.has(i.tagName.toUpperCase())){e.push(i);continue}for(let r of i.childNodes)if(r.nodeType===Node.TEXT_NODE&&r.nodeValue.trim()){e.push(i);break}}return e}var er=4;function xi(n){let e=typeof window<"u"&&window.devicePixelRatio||1;return`${n.clientWidth}x${n.clientHeight}@${e}`}var vt=class{constructor(e,t,{lazy:i,rootMargin:r,autoChrome:s=!0,modeSwitch:o=null,untrackedFallback:a="none"}){this.supported=!0,this.session=e,this.refSpace=t,this._windows=new Map,this._globalOverlays=new Set,this._isolatedBy=new WeakMap,this._autoChrome=s,this._autoChromeEls=new Set,this._lastChromeScan=0,this._fullTileWarned=new WeakSet,this._stoodDown=!1,this._activeModeIndex=-1,this._activeViewCount=0,this._hardwareDisplayState=null,this._modes=null,this._stereoCollapsed=!1,this._displayListeners=new Map,this._primedDisplayState=!1;let l=o&&typeof o=="object"?o:{};this._msEnabled=l.enabled!==!1,this._modeSwitch=new Ae((Number.isFinite(l.durationMs)?Math.max(0,l.durationMs):180)/1e3,qn(l.easing)),this._stereoFactor=1,this._msFire=null,this._msArmedUp=!1,this._msLastMs=null,this._msTick=null,this._trackingSupported=Oe(e)!==null,this._trackingState=this._trackingSupported?Oe(e):"unknown",this._untrackedFallback=a==="mono"?"mono":"none",this._bakedStereo=1,this._bakedTarget=1,this._bakedAt=null,this._bakedEaseS=(Number.isFinite(l.durationMs)?Math.max(0,l.durationMs):180)/1e3,this._applyUntrackedTarget(),this.undock=ut()?{model:!1,splat:!1}:null,this._undockRead=!1,this._running=!0,this._lazy=i,this._observer=i&&typeof IntersectionObserver=="function"?new IntersectionObserver(c=>this._onIntersect(c),{rootMargin:r}):null,this._loopId=0,this._framePending=!1,this._frameCount=0,this._frameWatchdog=null,this._suspended=null,U&&U._running&&U!==this&&console.warn("[inline3d] A second inline-3D session is live in this document. The browser's element-rect channel is a whole-widget setter, so both managers clobber each other's rect list every frame \u2014 tiles may flicker, ghost, or weave at a stale rect. Use ONE createInline3D() per document and add every window to it; if you are switching views, close() the previous manager first."),U=this,e.addEventListener("end",()=>this._teardown()),this._bindDisplayEvents(),this._bindTrackingEvents(),this._scanChrome(),this._bindLifecycle(),this._armDprWatch(),this._requestFrame()}get liveCount(){let e=0;for(let t of this._windows.values())t.layer&&e++;return e}addGlobalOverlay(e){if(!(!e||this._globalOverlays.has(e))){ne()&&pt(),this._globalOverlays.add(e);for(let t of this._windows.values())t.layer&&this._applyExclusion(t,e)}}removeGlobalOverlay(e){if(!(!e||!this._globalOverlays.delete(e)))for(let t of this._windows.values())t.layer&&this._dropExclusion(t,e)}_scanChrome(){if(ne()||!this._autoChrome||!Ie()||typeof document>"u")return;let e=Date.now();if(e-this._lastChromeScan<1e3)return;this._lastChromeScan=e;let t=document.body;if(!t)return;let i=new Set,r=t.querySelectorAll(":scope > *, :scope > * > *, :scope > * > * > *");for(let s of r){if(s.closest("[data-inline3d-no-overlay]"))continue;let o=getComputedStyle(s).position;if(o!=="fixed"&&o!=="sticky")continue;let a=!1;for(let l of this._windows.keys())if(s===l||s.contains(l)){a=!0;break}if(!a){i.add(s);for(let l of Qn(s))i.add(l)}}for(let s of this._autoChromeEls){let o=!1;if(s.isConnected){for(let a of this._windows.keys())if(s===a||s.contains(a)){o=!0;break}}(!s.isConnected||o)&&(this._autoChromeEls.delete(s),this.removeGlobalOverlay(s))}for(let s of i)this._globalOverlays.has(s)||(this._autoChromeEls.add(s),this.addGlobalOverlay(s))}addImage(e,t,i={}){let r=this._register(e,"image",i);return r.ready=ir(t).then(s=>{r.img=s,r.repaint()}),this._handle(e,r)}addVideo(e,t,i={}){let r=this._register(e,"video",i);return r.video=t,this._handle(e,r)}addScene(e,t,i={}){i.viewRig&&i.virtualDisplayHeight!==void 0&&Yn();let r=this._register(e,"scene",{virtualDisplayHeight:.24,...i});return r.onFrame=t,r.ownsBuffer=!1,i.bufferClamped===!0&&(r.warnedBufMismatch=!0),this._handle(e,r)}_handle(e,t){let i=this;return{remove:()=>this._remove(e),exclude:r=>{r&&(ne()&&pt(),t.excluded.add(r),this._applyExclusion(t,r))},unexclude:r=>{!r||!t.excluded.delete(r)||this._dropExclusion(t,r)},get trackingState(){return i._trackingState},setViewRig:r=>(t.viewRig=r||null,this._pushViewRig(t)),getDisplayInfo:()=>this._layerCall(t,"getDisplayInfo","getDisplayInfo()"),displayMetrics:async()=>{let r=null;try{r=await this._layerCall(t,"getDisplayInfo","getDisplayInfo()")}catch{}return si(r,e.getBoundingClientRect(),globalThis.devicePixelRatio||1)},getRenderingModes:()=>this._getRenderingModes(t),requestRenderingMode:r=>this._requestRenderingModeEased(r,t),setStereoEnabled:r=>this._setStereoEnabled(r,t),on:(r,s)=>this.on(r,s),off:(r,s)=>this.off(r,s),onDisplayModeChange:r=>this._onDisplayModeChange(r),stats:()=>({frames:t.frames,monoFrames:t.monoFrames}),get firstWoven(){return t.fwPromise},onFirstWoven:r=>{if(typeof r!="function")throw new TypeError("[inline3d] onFirstWoven() takes a function.");let s=!0;return t.fwPromise.then(o=>{if(s)try{r(o)}catch(a){console.error("[inline3d] onFirstWoven callback threw",a)}}),()=>{s=!1}},rewoven:()=>this._rewoven(t)}}getDisplayInfo(){return this._layerCall(this._liveWindow(null),"getDisplayInfo","getDisplayInfo()")}getRenderingModes(){return this._getRenderingModes(null)}requestRenderingMode(e){return this._requestRenderingModeEased(e,null)}setStereoEnabled(e){return this._setStereoEnabled(e,null)}get trackingState(){return this._trackingState}get hardwareDisplayState(){return this._hardwareDisplayState}get activeMode(){return{modeIndex:this._activeModeIndex,viewCount:this._activeViewCount}}get stereoCollapsed(){return this._stereoCollapsed}get modeSwitch(){return{active:this._msTransitionActive(),factor:this._stereoFactor}}close(){try{this.session.end()}catch{}this._teardown()}_effectiveViewRig(e){return this._stereoFactor>=1?e.viewRig||(e.stereoSynthRig?mt(e):null):(e.viewRig||(e.stereoSynthRig=!0),$n(e.viewRig||mt(e),this._stereoFactor))}_setStereoCollapsed(e){let t=!!e;if(this._stereoCollapsed!==t){this._stereoCollapsed=t,t&&Xn(),!t&&this._msArmedUp?(this._msArmedUp=!1,this._startUpRamp()):this._modeSwitch.active()||(this._stereoFactor=t?0:1);for(let i of this._windows.values()){if(t){let r=i.viewRig||mt(i);i.stereoSaved={ipdFactor:r.ipdFactor,parallaxFactor:r.parallaxFactor}}else i.stereoSaved=null;this._pushViewRig(i)}}}_pushViewRig(e){if(!ht())return Kn(),!1;if(!e.layer)return!1;let t=this._effectiveViewRig(e);try{return e.layer.setViewRig(t),!0}catch{return!1}}_layerCall(e,t,i,r=[]){if(!ft())return Promise.reject(new Error(`[inline3d] ${i} needs a DisplayXR Browser with the display-mode API (XRDisplayLayer.getDisplayInfo/getRenderingModes/requestRenderingMode). Gate on inline3dDisplayModesSupported().`));if(!e||!e.layer)return Promise.reject(new Error(`[inline3d] ${i} needs a live weave layer, and this window has none right now (lazy mode closes the layer while the tile is off screen). Call it once the tile is visible, or create the manager with { lazy: false }.`));try{return Promise.resolve(e.layer[t](...r))}catch(s){return Promise.reject(s)}}_liveWindow(e){if(e&&e.layer)return e;for(let t of this._windows.values())if(t.layer)return t;return e||null}async _getRenderingModes(e){let t=await this._layerCall(this._liveWindow(e),"getRenderingModes","getRenderingModes()"),i=Array.isArray(t)?t:[];this._modes=i;let r=i.find(s=>s.isActive);return r&&(this._activeModeIndex=r.modeIndex,this._activeViewCount=r.viewCount,(r.viewCount===1||r.viewCount===2)&&this._setStereoCollapsed(r.viewCount===1)),this._primedDisplayState=!0,t}_requestRenderingMode(e,t){return this._layerCall(this._liveWindow(t),"requestRenderingMode","requestRenderingMode()",[e])}_msTransitionActive(){return this._modeSwitch.active()||this._msArmedUp||this._msFire!==null}async _requestRenderingModeEased(e,t){if(!this._msEnabled||!ht())return this._requestRenderingMode(e,t);let i=this._modes;if(!Array.isArray(i)||i.length===0)try{i=await this._getRenderingModes(t)}catch{i=null}let r=(Array.isArray(i)?i:[]).find(a=>a&&a.modeIndex===e),s=r&&Number.isFinite(r.viewCount)?r.viewCount:0,o=this._activeViewCount;return s<1||s>2||o<1?this._requestRenderingMode(e,t):s===1?o===1?this._requestRenderingMode(e,t):this._rampDownThenRequest(e,t):this._requestThenRampUp(e,t)}_rampDownThenRequest(e,t){if(this._msFire&&this._msFire.modeIndex===e)return this._msFire.promise;this._settlePendingDown("superseded",`a request for mode ${e} replaced it`);let i={modeIndex:e,win:t,resolve:null,reject:null,promise:null};return i.promise=new Promise((r,s)=>{i.resolve=r,i.reject=s}),this._msFire=i,this._modeSwitch.request({targetMode:e,targetViewCount:1,currentMode:this._activeModeIndex,currentViewCount:this._activeViewCount,current:this._stereoFactor,steady:1}),this._msLastMs=V(),this._armModeSwitchTick(),i.promise}_requestThenRampUp(e,t){let r=this._msFire!==null&&e===this._activeModeIndex;this._settlePendingDown("superseded",`a request for mode ${e} reversed it`);let s=r?Promise.resolve(void 0):this._requestRenderingMode(e,t);return this._stereoFactor<1&&(this._stereoCollapsed?(this._msArmedUp=!0,this._modeSwitch.cancel(),this._stereoFactor=0):this._startUpRamp()),s.catch(o=>{throw this._msArmedUp&&(this._msArmedUp=!1,this._modeSwitch.active()||(this._stereoFactor=this._stereoCollapsed?0:1)),o})}_startUpRamp(){this._settlePendingDown("superseded","the display returned to 3D"),this._modeSwitch.request({targetMode:this._activeModeIndex,targetViewCount:2,currentMode:this._activeModeIndex,currentViewCount:2,current:this._stereoFactor,steady:1}),this._msLastMs=V(),this._armModeSwitchTick()}_settlePendingDown(e,t){let i=this._msFire;if(!i)return;this._msFire=null;let r=new Error(`[inline3d] the request for rendering mode ${i.modeIndex} was never forwarded: ${t}. A ->2D switch is held until the disparity has ramped out, so a request that is reversed or replaced in that window is dropped rather than fired late.`);r.name=e,i.reject(r)}_advanceModeSwitch(){if(!this._modeSwitch.active()){this._msLastMs=null,this._disarmModeSwitchTick();return}let e=V(),t=typeof this._msLastMs=="number"?Math.max(0,(e-this._msLastMs)/1e3):0;this._msLastMs=e;let i=this._modeSwitch.update(t);if(i.factor!==this._stereoFactor){this._stereoFactor=i.factor;for(let r of this._windows.values())this._pushViewRig(r)}if(i.fire&&this._msFire){let r=this._msFire;this._msFire=null,this._requestRenderingMode(r.modeIndex,r.win).then(s=>r.resolve(s),s=>{this._startUpRamp(),r.reject(s)})}this._modeSwitch.active()||(this._msLastMs=null,this._disarmModeSwitchTick())}_armModeSwitchTick(){this._msTick!==null||typeof setTimeout!="function"||(this._msTick=setTimeout(()=>{this._msTick=null,this._running&&(this._advanceModeSwitch(),this._modeSwitch.active()&&this._armModeSwitchTick())},Un))}_disarmModeSwitchTick(){this._msTick!==null&&(typeof clearTimeout=="function"&&clearTimeout(this._msTick),this._msTick=null)}async _setStereoEnabled(e,t){let i=e?2:1,r=await this._getRenderingModes(t),s=Array.isArray(r)?r:[],o=s.find(a=>a.viewCount===i&&a.isRequestable);if(!o)throw new Error(`[inline3d] setStereoEnabled(${!!e}) found no requestable ${i}-view mode on this display (${s.length} mode(s) listed). It is sugar over requestRenderingMode() and cannot invent one \u2014 read getRenderingModes() and drive the list yourself.`);return o.isActive&&!this._msTransitionActive()||await this._requestRenderingModeEased(o.modeIndex,t),!!e}_bindDisplayEvents(){let e=this.session;!e||typeof e.addEventListener!="function"||ft()&&(e.addEventListener("renderingmodechange",t=>{this._onRenderingModeChange(t).catch(()=>{})}),e.addEventListener("hardwaredisplaystatechange",t=>{this._onHardwareDisplayStateChange(t).catch(()=>{})}))}_onHardwareDisplayStateChange(e){let t=Jn(e),i=_t(e),r=a=>{a&&(this._hardwareDisplayState=a),this._emitDisplay({type:"hardwaredisplaystatechange",state:a||this._hardwareDisplayState,detail:i})};t&&r(t);let s=this._activeModeIndex,o=this._activeViewCount;return this._getRenderingModes(null).then(a=>{let l=(Array.isArray(a)?a:[]).find(c=>c.isActive)||null;if(l&&(l.modeIndex!==s||l.viewCount!==o)&&this._emitDisplay({type:"renderingmodechange",modeIndex:this._activeModeIndex,viewCount:this._activeViewCount||null,mode:l,detail:null}),!t){let c=l&&typeof l.hardwareDisplay3D=="boolean"?l.hardwareDisplay3D?"3d":"2d":null;r(c)}}).catch(()=>{t||r(null)})}async _onRenderingModeChange(e){let t=_t(e),i=Gn(e),r=null;try{let s=await this._getRenderingModes(null),o=Array.isArray(s)?s:[];r=(i>=0?o.find(a=>a.modeIndex===i):null)||o.find(a=>a.isActive)||null}catch{}r?(this._activeModeIndex=r.modeIndex,this._activeViewCount=r.viewCount):i>=0&&(this._activeModeIndex=i),(this._activeViewCount===1||this._activeViewCount===2)&&this._setStereoCollapsed(this._activeViewCount===1),this._emitDisplay({type:"renderingmodechange",modeIndex:this._activeModeIndex,viewCount:this._activeViewCount||null,mode:r,detail:t})}_emitDisplay(e,t){let i=this._displayListeners.get(e.type);if(!i)return;let r=t||[e];for(let s of[...i])try{s(...r)}catch(o){console.error(`[inline3d] ${e.type} listener threw`,o)}}on(e,t){if(typeof t!="function")throw new TypeError("[inline3d] on() takes (type, function).");if(!mi.includes(e))throw new TypeError(`[inline3d] on() knows ${mi.join(" / ")}, got ${JSON.stringify(e)}.`);let i=this._displayListeners.get(e);return i||this._displayListeners.set(e,i=new Set),i.add(t),()=>this.off(e,t)}off(e,t){let i=this._displayListeners.get(e);i&&i.delete(t)}_onDisplayModeChange(e){if(typeof e!="function")throw new TypeError("[inline3d] onDisplayModeChange() takes a function.");let t=Si.map(i=>this.on(i,e));return()=>{for(let i of t)i()}}async refreshUndock(){if(!ut())return this.undock=null;let e=this._liveWindow(null);if(!e||!e.layer||typeof e.layer.getUndockCapabilities!="function")return this.undock;try{let t=await e.layer.getUndockCapabilities();this.undock={model:!!(t&&t.model),splat:!!(t&&t.splat)}}catch{}return this.undock}_register(e,t,i){this._windows.has(e)&&this._remove(e),e.style.willChange="transform",e.style.transform="translateZ(0)";let r={canvas:e,kind:t,layer:null,img:null,video:null,onFrame:null,onLayerLost:typeof i.onLayerLost=="function"?i.onLayerLost:null,layerLostSent:!1,ready:null,ownsBuffer:t!=="scene",cornerRadius:i.cornerRadius||0,feather:i.feather||0,reqW:i.width||0,reqH:i.height||0,virtualDisplayHeight:i.virtualDisplayHeight||0,viewRig:i.viewRig||null,stereoSaved:null,stereoSynthRig:!1,observeEl:i.observe||e,ctx:t==="scene"?null:e.getContext("2d"),repaint:()=>this._paint(r,null),excluded:new Set,autoExcluded:new Set,overlayObserver:null,sizeObserver:null,resizePending:!1,frames:0,monoFrames:0,fwResult:null,fwResolve:null,fwPromise:null,fwHoldMs:tr(i.firstWovenHoldMs),fwRegAt:V(),fwLayerAt:null,fwStereo:!1,rw:null,rwGone:null};return r.fwPromise=new Promise(s=>{r.fwResolve=s}),this._windows.set(e,r),this._lazy&&this._observer?this._observer.observe(r.observeEl):this._activate(r),r}_remove(e){let t=this._windows.get(e);t&&(this._observer&&this._observer.unobserve(t.observeEl),this._deactivate(t),this._windows.delete(e),this._settleFirstWoven(t,!1,"removed"))}_onIntersect(e){for(let t of e){let i=null;for(let r of this._windows.values())if(r.observeEl===t.target){i=r;break}i&&(t.isIntersecting?this._activate(i):this._deactivate(i))}}_activate(e){if(!e.layer){this._scanChrome();try{let t=ht()?this._effectiveViewRig(e):null,i=t?{viewRig:t}:e.virtualDisplayHeight>0?{virtualDisplayHeight:e.virtualDisplayHeight}:{};e.layer=new XRDisplayLayer(this.session,e.canvas,i)}catch(t){e.layer=null,e.layerFailWarned||(e.layerFailWarned=!0,console.warn("[inline3d] new XRDisplayLayer() failed for this window \u2014 it will show FLAT 2D instead of woven 3D, and the SDK will not retry. The canvas has been repainted mono so it cannot be left holding a raw side-by-side pair.",t)),this._paintMono(e),this._notifyLayerLost(e),this._settleFirstWoven(e,!1,"layer-failed");return}e.fwResult||(e.fwLayerAt=V(),e.fwStereo=!1),this._restartRewoven(e),e.layerLostSent=!1,!this._primedDisplayState&&ft()&&(this._primedDisplayState=!0,this._getRenderingModes(e).catch(()=>{this._primedDisplayState=!1})),ut()&&this.undock&&!this._undockRead&&(this._undockRead=!0,this.refreshUndock().catch(()=>{})),Vn(e.layer)===!0&&this._standDownLegacyOcclusion();for(let t of e.excluded)this._applyExclusion(e,t);for(let t of this._globalOverlays)this._applyExclusion(e,t);this._startOverlayScan(e),e.ownsBuffer&&(this._sizeBuffer(e,!0),this._paint(e,null)),this._startSizeWatch(e)}}_deactivate(e){if(this._stopOverlayScan(e),this._stopSizeWatch(e),e.layer){try{e.layer.close()}catch{}e.layer=null}this._paintMono(e)}_paintMono(e){!e.ownsBuffer||e.kind==="scene"||(this._sizeBuffer(e,!1),this._paint(e,null))}_notifyLayerLost(e){if(!(e.kind!=="scene"||typeof e.onLayerLost!="function"||e.layerLostSent)){e.layerLostSent=!0;try{e.onLayerLost()}catch(t){console.warn("[inline3d] a scene window's onLayerLost callback threw",t)}}}_isFullTileOverlay(e,t){if(!t||typeof t.getBoundingClientRect!="function")return!1;let i=t.getBoundingClientRect(),r=e.canvas.getBoundingClientRect(),s=i.width*i.height,o=r.width*r.height;if(s<=0||o<=0)return!1;let a=Math.min(i.right,r.right)-Math.max(i.left,r.left),l=Math.min(i.bottom,r.bottom)-Math.max(i.top,r.top);if(a<=0||l<=0)return!1;let c=a*l;return c/s<bi||c/o<bi?!1:(this._fullTileWarned.has(t)||(this._fullTileWarned.add(t),console.warn("[inline3d] Refusing a full-tile overlay: this element covers its own woven canvas, and the browser's geometric matcher cannot tell the two apart \u2014 it would stage the CANVAS as the overlay and the tile would show its raw side-by-side buffer instead of 3D. Make the overlay a PARTIAL region of the tile (a caption band, a badge, a corner plate), or move it outside the tile and register it with addGlobalOverlay().",t)),!0)}_applyExclusion(e,t){if(ne()||!e.layer||!Ie()||this._isFullTileOverlay(e,t))return;let i=this._isolatedBy.get(t);if(i||(i=new Set,this._isolatedBy.set(t,i)),i.add(e),!t.dataset.inline3dIsolated){t.dataset.inline3dPriorWillChange=t.style.willChange||"";let r=t.style.willChange&&t.style.willChange!=="auto"?t.style.willChange+", transform":"transform";t.style.willChange=r,t.dataset.inline3dIsolated="1"}try{e.layer.excludeElement(t)}catch{}}_dropExclusion(e,t){if(ne())return;let i=this._isolatedBy.get(t);if(i&&i.delete(e),(!i||i.size===0)&&this._unpromote(t),!(!e.layer||!Ie()))try{e.layer.unexcludeElement(t)}catch{}}_unpromote(e){return!e||!e.dataset||!e.dataset.inline3dIsolated?!1:(e.style.willChange=e.dataset.inline3dPriorWillChange||"",delete e.dataset.inline3dPriorWillChange,delete e.dataset.inline3dIsolated,!0)}_standDownLegacyOcclusion(){if(this._stoodDown)return;this._stoodDown=!0;let e=!1;for(let t of this._windows.values()){t.overlayObserver&&(this._stopOverlayScan(t),e=!0);for(let i of t.excluded)this._unpromote(i)&&(e=!0)}for(let t of this._autoChromeEls)this._globalOverlays.delete(t),this._unpromote(t),e=!0;this._autoChromeEls.clear();for(let t of this._globalOverlays)this._unpromote(t)&&(e=!0);this._isolatedBy=new WeakMap,e&&pt()}_startOverlayScan(e){if(ne()||!Ie()||typeof MutationObserver!="function")return;let t=e.canvas.parentElement;if(!t)return;let i=()=>{let r=new Set(t.querySelectorAll("[data-inline3d-overlay]"));for(let s of e.autoExcluded)r.has(s)||(e.autoExcluded.delete(s),this._dropExclusion(e,s));for(let s of r)e.autoExcluded.has(s)||(e.autoExcluded.add(s),this._applyExclusion(e,s))};i(),e.overlayObserver=new MutationObserver(i),e.overlayObserver.observe(t,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-inline3d-overlay"]})}_stopOverlayScan(e){e.overlayObserver&&(e.overlayObserver.disconnect(),e.overlayObserver=null),e.autoExcluded.clear()}_eyeSize(e,t=!0){let i=Math.min(window.devicePixelRatio||1,2),r=e.reqW||Math.round((e.canvas.clientWidth||256)*i),s=e.reqH||Math.round((e.canvas.clientHeight||256)*i),o=1,a=!e.reqW&&!e.reqH&&this._sourceEyeSize(e);if(a){let c=Math.max(a.w/r,a.h/s);c<1&&(o=c,r=Math.max(1,Math.round(r*c)),s=Math.max(1,Math.round(s*c)))}let l=ci(r,s,li(),{cols:t?2:1});return l.clamped&&(o*=l.scale,r=l.eyeW,s=l.eyeH,e.warnedBufClamp||(e.warnedBufClamp=!0,console.warn(di("[inline3d]",l)))),e.bufScale=o,{w:r,h:s}}_sourceEyeSize(e){if(e.kind!=="video"&&e.kind!=="image")return null;let t=e.kind==="video"?e.video:e.img;if(!t)return null;let i=t.videoWidth||t.naturalWidth||t.width,r=t.videoHeight||t.naturalHeight||t.height;return!(i>1)||!(r>0)?null:{w:i/2,h:r}}_checkSceneBuffer(e){let t=e.canvas;if(!t||typeof t.getContext!="function")return;if(e.sceneGl===void 0){let r=null;try{r=t.getContext("webgl2")||t.getContext("webgl")}catch{r=null}e.sceneGl=r&&typeof r.drawingBufferWidth=="number"?r:null}if(!e.sceneGl)return;let i=hi(t,e.sceneGl);i.mismatch&&(e.warnedBufMismatch=!0,console.warn(fi("[inline3d]",t,i,"getViewport() splits canvas.width, so the eyes are off-centre in the woven buffer. This scene canvas is sized by the page: keep 2 \xD7 eye width and the height within MAX_TEXTURE_SIZE / MAX_RENDERBUFFER_SIZE / MAX_VIEWPORT_DIMS, or map getViewport() onto gl.drawingBufferWidth/Height.")))}_sizeBuffer(e,t){let{w:i,h:r}=this._eyeSize(e,t);e.eyeW=i,e.eyeH=r,e.canvas.width=t?i*2:i,e.canvas.height=r,e.sbs=t}_startSizeWatch(e){typeof ResizeObserver=="function"&&(e.sizeObserver||!e.ownsBuffer||e.reqW&&e.reqH||(e.sizeObserver=new ResizeObserver(()=>this._onBoxChange(e)),e.sizeObserver.observe(e.canvas)))}_stopSizeWatch(e){e.sizeObserver&&(e.sizeObserver.disconnect(),e.sizeObserver=null),e.resizePending=!1}_onBoxChange(e){if(!e.layer||!e.ownsBuffer||e.resizePending)return;e.resizePending=!0;let t=()=>{if(!e.resizePending||(e.resizePending=!1,!e.layer||!e.ownsBuffer))return;this._noteRewovenBox(e);let{w:i,h:r}=this._eyeSize(e);i===e.eyeW&&r===e.eyeH||(this._sizeBuffer(e,!0),this._paint(e,null))};typeof requestAnimationFrame=="function"?requestAnimationFrame(t):t()}_armDprWatch(){if(typeof window>"u"||typeof window.matchMedia!="function")return;this._disarmDprWatch();let e;try{e=window.matchMedia(`(resolution: ${window.devicePixelRatio||1}dppx)`)}catch{return}let t=()=>{if(this._running){this._armDprWatch();for(let i of this._windows.values())i.layer&&this._onBoxChange(i)}};try{e.addEventListener("change",t)}catch{return}this._dprWatch={q:e,onChange:t}}_disarmDprWatch(){if(this._dprWatch){try{this._dprWatch.q.removeEventListener("change",this._dprWatch.onChange)}catch{}this._dprWatch=null}}_paint(e,t){if(e.kind==="scene"||!e.ctx)return;let i=this._running&&!!e.layer;!i&&e.sbs&&this._sizeBuffer(e,!1);let r=e.kind==="video"?e.video:e.img;if(!r)return;if(e.kind==="video"&&(r.readyState||0)<2){i&&this._recommitLastFrame(e);return}let s=e.canvas,o=e.ctx,a=r.videoWidth||r.naturalWidth||r.width,l=r.videoHeight||r.naturalHeight||r.height;if(!a||!l)return;let c=a+"x"+l;if(e.srcKey!==c&&(e.srcKey=c,e.ownsBuffer&&!(e.reqW&&e.reqH))){let{w:u,h:v}=this._eyeSize(e,e.sbs);(u!==e.eyeW||v!==e.eyeH)&&this._sizeBuffer(e,e.sbs)}let p=e.bufScale||1,f=e.cornerRadius*p,h=e.feather*p;if(o.clearRect(0,0,s.width,s.height),!e.sbs){Pe(o,r,0,0,a/2,l,0,0,s.width,s.height,f,h);return}let d=s.width/2,m=Math.min(this._stereoFactor,this._bakedStereo);if(m<1){Pe(o,r,0,0,a/2,l,0,0,d,s.height,f,h),nr(o,r,a/2,l,d,s.height,m,f,h);return}f>0||h>0?(Pe(o,r,0,0,a/2,l,0,0,d,s.height,f,h),Pe(o,r,a/2,0,a/2,l,d,0,d,s.height,f,h)):o.drawImage(r,0,0,a,l,0,0,s.width,s.height)}_bindTrackingEvents(){let e=this.session;!e||typeof e.addEventListener!="function"||this._trackingSupported&&e.addEventListener(gt,()=>{this._setTrackingState(Oe(e)||"unknown")})}_setTrackingState(e){let t=Mi.includes(e)?e:"unknown";if(t===this._trackingState)return;this._trackingState=t,this._applyUntrackedTarget();let i={type:gt,state:t};this._emitDisplay(i,[t,i])}_applyUntrackedTarget(){if(this._untrackedFallback!=="mono"){this._bakedTarget=1;return}this._trackingState==="searching"?this._bakedTarget=0:this._trackingState==="tracking"&&(this._bakedTarget=1)}_trackBakedStereo(e){this._trackingSupported&&this._setTrackingState(Oe(this.session)||"unknown");let t=this._bakedAt===null||!Number.isFinite(e)?0:Math.max(0,(e-this._bakedAt)/1e3);this._bakedAt=Number.isFinite(e)?e:this._bakedAt;let i=this._bakedStereo,r=this._bakedTarget;if(i===r)return;let s=this._bakedEaseS>0?t/this._bakedEaseS:1;this._bakedStereo=r>i?Math.min(r,i+s):Math.max(r,i-s)}_recommitLastFrame(e){let t=e.canvas;if(!t.width||!t.height)return;let i=e.ctx;try{i.save(),i.globalCompositeOperation="copy",i.drawImage(t,0,0),i.restore()}catch{}}_requestFrame(e){if(!this._running||this._framePending&&!e)return;let t=e?++this._loopId:this._loopId;this._framePending=!0;try{this.session.requestAnimationFrame((i,r)=>{t===this._loopId&&(this._framePending=!1,this._frameCount++,this._frame(i,r))})}catch{this._framePending=!1}}_frame(e,t){if(!this._running)return;this._requestFrame(),this._advanceModeSwitch();let i=this.refSpace?t.getViewerPose(this.refSpace):null,r=i?i.views:null;this._trackBakedStereo(e);for(let s of this._windows.values())if(s.layer){if(s.kind==="scene"){if(r&&s.onFrame){if(s.frames++,r.length<2&&(s.monoFrames++,s.monoFrames%300===1&&typeof console<"u"&&console.debug)){let o=(100*s.monoFrames/Math.max(1,s.frames)).toFixed(1);console.debug(`[inline3d] scene window: ${s.monoFrames} non-stereo view lists in ${s.frames} frames (${o}%). The viewer replays its last good stereo frame for these; a rising rate means the session is falling back under load.`)}try{s.onFrame(r,s.layer,t),r.length>=2&&(s.fwStereo=!0,s.warnedBufMismatch||this._checkSceneBuffer(s),s.rw&&(s.rw.stereo=!0))}catch(o){s.frameThrewWarned||(s.frameThrewWarned=!0,console.warn("[inline3d] a scene window's onFrame threw; this window will keep whatever it last drew, and the other windows carry on. Further throws from it are silent.",o))}}}else this._paint(s,r),s.sbs&&(s.kind==="video"?(s.video&&s.video.readyState||0)>=2:s.img)&&(s.fwStereo=!0,s.rw&&(s.rw.stereo=!0));this._tickFirstWoven(s)}}_tickFirstWoven(e){if(e.rw){this._noteRewovenBox(e);let t=e.rw,i=V();t.stereo&&i-t.at>=e.fwHoldMs?this._settleRewoven(e,!0,"hold-elapsed"):t.at>t.calledAt&&i-t.calledAt>=er*e.fwHoldMs&&this._settleRewoven(e,!0,"hold-capped")}e.fwResult||!e.fwStereo||e.fwLayerAt===null||V()-e.fwLayerAt<e.fwHoldMs||this._settleFirstWoven(e,!0,"hold-elapsed")}_settleFirstWoven(e,t,i){t||(e.rwGone||(e.rwGone=i),this._settleRewoven(e,!1,i)),!e.fwResult&&(e.fwResult=Object.freeze({woven:t,confirmed:!1,reason:i,ms:Math.round(V()-e.fwRegAt)}),e.fwResolve(e.fwResult),e.fwResolve=null)}_rewoven(e){if(!e.fwResult)return e.fwPromise;if(!e.fwResult.woven)return Promise.resolve(e.fwResult);if(e.rwGone)return Promise.resolve(Object.freeze({woven:!1,confirmed:!1,reason:e.rwGone,ms:0}));if(e.rw)return this._restartRewoven(e),e.rw.promise;let t,i=new Promise(s=>{t=s}),r=V();return e.rw={promise:i,resolve:t,calledAt:r,at:r,stereo:!1,box:xi(e.canvas)},i}_noteRewovenBox(e){let t=e.rw;if(!t)return;let i=xi(e.canvas);i!==t.box&&(t.box=i,this._restartRewoven(e))}_restartRewoven(e){e.rw&&(e.rw.at=V(),e.rw.stereo=!1)}_settleRewoven(e,t,i){let r=e.rw;r&&(e.rw=null,r.resolve(Object.freeze({woven:t,confirmed:!1,reason:i,ms:Math.round(V()-r.calledAt)})))}_bindLifecycle(){typeof window>"u"||(this._onPageHide=()=>this._suspend(),this._onPageShow=e=>this._resume(!!(e&&e.persisted)),window.addEventListener("pagehide",this._onPageHide),window.addEventListener("pageshow",this._onPageShow),typeof document<"u"&&"onfreeze"in document&&(this._onFreeze=()=>this._suspend(),this._onResume=()=>this._resume(!0),document.addEventListener("freeze",this._onFreeze),document.addEventListener("resume",this._onResume)))}_unbindLifecycle(){typeof window>"u"||(this._onPageHide&&window.removeEventListener("pagehide",this._onPageHide),this._onPageShow&&window.removeEventListener("pageshow",this._onPageShow),this._onFreeze&&typeof document<"u"&&(document.removeEventListener("freeze",this._onFreeze),document.removeEventListener("resume",this._onResume)),this._onPageHide=this._onPageShow=this._onFreeze=this._onResume=null,this._frameWatchdog&&(clearTimeout(this._frameWatchdog),this._frameWatchdog=null))}_suspend(){if(!this._running||this._suspended)return;let e=[];for(let t of this._windows.values())t.layer&&(e.push(t),this._deactivate(t));this._suspended=e}_resume(e){if(!this._running)return;let t=this._suspended;if(this._suspended=null,t)for(let i of t)this._windows.has(i.canvas)&&(this._lazy&&this._observer?(this._observer.unobserve(i.observeEl),this._observer.observe(i.observeEl)):this._activate(i));this._lastChromeScan=0,this._scanChrome(),this._armDprWatch(),e&&this._watchForStalledFrames()}_watchForStalledFrames(){if(this._frameWatchdog||typeof setTimeout!="function")return;let e=this._frameCount;this._frameWatchdog=setTimeout(()=>{this._frameWatchdog=null,!(!this._running||this._frameCount!==e)&&this._requestFrame(!0)},1e3)}_teardown(){if(this._running){this._running=!1,U===this&&(U=null),this._unbindLifecycle(),this._disarmDprWatch(),this._disarmModeSwitchTick(),this._modeSwitch.cancel(),this._msArmedUp=!1,this._settlePendingDown("closed","the inline-3D session closed first"),this._observer&&this._observer.disconnect();for(let e of this._windows.values()){if(this._stopOverlayScan(e),this._stopSizeWatch(e),e.layer){try{e.layer.close()}catch{}e.layer=null}this._paintMono(e),this._notifyLayerLost(e),this._settleFirstWoven(e,!1,"session-ended")}this._windows.clear(),this._setTrackingState("unknown"),this._displayListeners.clear()}}};function tr(n){return typeof n=="number"&&Number.isFinite(n)&&n>=0?n:Bn}function ir(n){return typeof n!="string"?Promise.resolve(n):new Promise((e,t)=>{let i=new Image;i.decoding="async",i.onload=()=>e(i),i.onerror=t,i.src=n})}function Pe(n,e,t,i,r,s,o,a,l,c,p,f){p>0&&n.roundRect?(n.save(),n.beginPath(),n.roundRect(o,a,l,c,p),n.clip(),n.drawImage(e,t,i,r,s,o,a,l,c),n.restore()):n.drawImage(e,t,i,r,s,o,a,l,c),f>0&&Ci(n,o,a,l,c,f)}function nr(n,e,t,i,r,s,o,a,l){n.save(),a>0&&n.roundRect&&(n.beginPath(),n.roundRect(r,0,r,s,a),n.clip()),n.drawImage(e,0,0,t,i,r,0,r,s),o>0&&(n.globalAlpha=o,n.drawImage(e,t,0,t,i,r,0,r,s)),n.restore(),l>0&&Ci(n,r,0,r,s,l)}function Ci(n,e,t,i,r,s){let o=Math.min(s,Math.floor(Math.min(i,r)/2));if(o<=0)return;n.save(),n.globalCompositeOperation="destination-out";let a=[[e,t,i,o,[e,t],[e,t+o]],[e,t+r-o,i,o,[e,t+r],[e,t+r-o]],[e,t,o,r,[e,t],[e+o,t]],[e+i-o,t,o,r,[e+i,t],[e+i-o,t]]];for(let[l,c,p,f,h,d]of a){let m=n.createLinearGradient(h[0],h[1],d[0],d[1]);m.addColorStop(0,"rgba(0,0,0,1)"),m.addColorStop(1,"rgba(0,0,0,0)"),n.fillStyle=m,n.fillRect(l,c,p,f)}n.restore()}function se(n,e){return n>0&&e>0&&n/e>2.5}function X(n,e,t,i,r){let s=Math.abs(i||0),o=Math.min(n-2*s,e*t);o=Math.max(1,o);let a=Math.min(e,o/t);o=a*t;let l=(n-o)/2+(r===0?i:-i);return{sx:Math.max(0,Math.min(n-o,l)),sy:(e-a)/2,sw:o,sh:a}}function be(n,e,t){let i=Math.min(n,e*t),r=i/t;return{w:Math.max(2,Math.round(i/2)*2),h:Math.max(2,Math.round(r/2)*2)}}function oe(n,e){let t=n/2;return[{src:"R",sx:t,sw:t,sy:0,sh:e,dx:0,dw:t,mirror:!0},{src:"L",sx:0,sw:t,sy:0,sh:e,dx:t,dw:t,mirror:!0}]}function yt(n,e,t){let i=new n.constructor(n.length);for(let r of oe(e,t))for(let s=0;s<t;s++)for(let o=0;o<r.dw;o++){let a=r.sx+(r.sw-1-o);i[s*e+r.dx+o]=n[s*e+a]}return i}function Ri(n,e){return!(n>0)||!(e>0)||e>=180?null:n/2/Math.tan(e/2*Math.PI/180)}function je({eyeWidthPx:n,hfovDeg:e,baselineMm:t,subjectZmm:i}){let r=Ri(n,e);return r===null||!(t>0)||!(i>0)?0:r*t/(2*i)}function We(n,e,t=.12){let i=Math.max(0,e*t);return Math.max(-i,Math.min(i,n||0))}function Ne(n,e,t=.2){let i=n+t*(e-n);return Math.abs(e-i)<.05?e:i}function xe(){let n={hello:null,subjectZmm:null,measuredPx:null,depth:0,current:0,target(e){let t=n.measuredPx!==null?n.measuredPx/2:n.hello&&n.subjectZmm?je({eyeWidthPx:e,hfovDeg:n.hello.hfovDeg,baselineMm:n.hello.baselineMm,subjectZmm:n.subjectZmm}):0;return We(t+n.depth*.05*e,e)},step(e){return n.current=Ne(n.current,n.target(e)),n.current}};return n}var ze=1,wt="inline3d-call/1",Di=Object.freeze(["sbs","mono"]),ae=4,Li=4,bt=5,rr=150,sr=5e3,or=/^[A-Za-z0-9_-]{16,64}$/,ar=16;function xt(n){let e=new Uint8Array(ar);return(n||(i=>globalThis.crypto.getRandomValues(i)))(e),Ii(e)}function Ai(n){let e=new Uint8Array(8);return(n||(i=>globalThis.crypto.getRandomValues(i)))(e),Ii(e)}function Ii(n){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",t="",i=0;for(;i+2<n.length;i+=3){let s=n[i]<<16|n[i+1]<<8|n[i+2];t+=e[s>>18&63]+e[s>>12&63]+e[s>>6&63]+e[s&63]}let r=n.length-i;if(r===1){let s=n[i]<<16;t+=e[s>>18&63]+e[s>>12&63]}else if(r===2){let s=n[i]<<16|n[i+1]<<8;t+=e[s>>18&63]+e[s>>12&63]+e[s>>6&63]}return t}function le(n){return typeof n=="string"&&or.test(n)}function Se(n){if(!n)return null;let e="";if(typeof n=="object")e=n.hash||n.href&&String(n.href).split("#")[1]||"";else{let t=String(n),i=t.indexOf("#");e=i>=0?t.slice(i+1):t.includes("=")&&!t.includes("://")?t:""}e=e.replace(/^#/,"");for(let t of e.split("&")){let i=t.indexOf("=");if(i<0||decodeURIComponent(t.slice(0,i))!=="room")continue;let r=decodeURIComponent(t.slice(i+1));return le(r)?r:null}return null}function He(n,e){if(!le(e))throw new Error(`@displayxr/inline3d/call: invalid room id "${e}"`);return`${String(n||"").split("#")[0]}#room=${e}`}function St(n){if(!n||typeof n!="object"||n.type!=="hello")return null;let e=(t,i,r)=>typeof t=="number"&&Number.isFinite(t)&&t>=i&&t<=r?t:null;return{type:"hello",v:typeof n.v=="number"?n.v:ze,format:Di.includes(n.format)?n.format:"mono",width:e(n.width,1,16384),height:e(n.height,1,16384),baselineMm:e(n.baselineMm,1,1e3),hfovDeg:e(n.hfovDeg,5,170),rectified:n.rectified===!0,sdk:typeof n.sdk=="string"?n.sdk.slice(0,64):null}}function Mt({format:n,width:e,height:t,baselineMm:i,hfovDeg:r,rectified:s}={}){let o={type:"hello",v:ze,format:Di.includes(n)?n:"mono",width:e||0,height:t||0,rectified:!!s,sdk:wt};return Number.isFinite(i)&&(o.baselineMm=i),Number.isFinite(r)&&(o.hfovDeg=r),o}function Et(n){if(!n||n.type!=="hint")return null;let e=n.subjectZmm;return typeof e=="number"&&Number.isFinite(e)&&e>=rr&&e<=sr?{type:"hint",subjectZmm:e}:null}function Oi(n){return!n||n.type!=="state"?null:{type:"state",muted:n.muted===!0,cameraOff:n.cameraOff===!0,speaking:n.speaking===!0}}function kt(n){let e=1e3/n,t=-1/0;return i=>i-t<e?!1:(t=i,!0)}function Tt({format:n,woven:e,mono3D:t="auto",lift:i=!1,overBudget:r=!1,failed:s=!1}){return(n==="sbs"?"sbs":"mono")==="sbs"?{route:e?"woven-sbs":"flat-left"}:e?t==="off"||t===!1?{route:"flat",mono3d:"off"}:i?s?{route:"flat",mono3d:"failed"}:r?{route:"flat",mono3d:"budget"}:{route:"lifted",mono3d:"lifted"}:{route:"flat",mono3d:"unavailable"}:{route:"flat"}}function Ct(n){return n==="woven-sbs"?"3D":n==="lifted"?"2D\u21923D":"2D"}function Rt({need:n=10,needNoPose:e=30}={}){let t=0,i=0,r=!1;return{feed(s){return r?!0:(i++,s===null?r=i>=e:(t=s>=1?t+1:0,r=t>=n),r)},get live(){return r}}}function Ve(n,e){let t=Math.max(1,e|0),r=n==="sbs"?[6e3,4e3,3e3]:[2500,1800,1400];return r[Math.min(t,r.length)-1]}function B(n,{baseMs:e=1e3,maxMs:t=3e4,rand:i=Math.random}={}){let r=Math.min(t,e*Math.pow(2,Math.max(0,n)));return Math.round(r*(.8+.4*i()))}var Me=Object.freeze(["VP9","VP8","AV1"]);function cr(n,e=Me){let t=e.indexOf(String(n||"").toUpperCase());return t<0?e.length:t}function $e(n,e=Me){let t=i=>cr(String(i.mimeType||"").split("/")[1],e);return n.map((i,r)=>({c:i,i:r,r:t(i)})).sort((i,r)=>i.r-r.r||i.i-r.i).map(i=>i.c)}function Ee(n,e=Me){if(!n)return n;let t=n.includes(`\r
|
|
1
|
+
/* @displayxr/inline3d 1.35.0 — dist/call.js — Apache-2.0 — https://github.com/DisplayXR/displayxr-web */
|
|
2
|
+
var _e=Object.freeze({speaker:"high",other:"normal",hidden:"paused"}),Cn=["high","normal","low","paused"],Rn=.02,Dn=1e3/20,Ln=3e3,An=1e3/28;function ye(n){return typeof n=="function"?n:n===!1||n==="off"?"off":"auto"}function it(n=import.meta.url){return ge?typeof ge=="function"?ge():ge:new URL("../lift/index.js",n).href}var ge=null;function ii(n){ge=n||null}function On(){return import(it())}async function nt(n,{importer:e=On,nav:t=globalThis.navigator,log:i=null,capsOpts:r={webFallback:!0}}={}){let s=(h,d)=>i&&i(h,d),o=(h,d={})=>(s("lift-unavailable",{reason:h,...d}),{lift:null,capabilities:null,caps:null,source:"none",reason:h}),a=ye(n);if(a==="off")return{lift:null,capabilities:null,caps:null,source:"none",reason:"off"};if(typeof a=="function"){let h=typeof a.liftCapabilities=="function"?a.liftCapabilities:null;return{lift:a,capabilities:h,caps:null,source:"injected",reason:null}}let l;try{l=await e()}catch(h){return o("import-failed",{message:String(h&&h.message||h).slice(0,200)})}let c=l&&typeof l.lift=="function"?l.lift:null;if(!c)return o("no-lift-export");let p=typeof l.liftCapabilities=="function"?l.liftCapabilities:null,f=null;if(p){try{f=await p(r)}catch{f=null}let h=!!(f&&f.webFallback&&f.webFallback.webgpu);if(f&&!f.native&&!h)return o("no-provider",{native:!1,webgpu:!1})}else if(!(t&&t.gpu))return o("no-webgpu");return s("lift-ready",{native:!!(f&&f.native),provider:f&&f.provider||null}),{lift:c,capabilities:p,caps:f,source:"module",reason:null}}function ve(n){let e=Number.isFinite(+n)&&n!==null?Math.max(-1,Math.min(1,+n)):0;return Math.abs(e)<Rn?"auto":Math.round((.5+.5*e)*1e3)/1e3}function Le({id:n,speakerId:e,visible:t=!0}){return t?n!=null&&n===e?_e.speaker:_e.other:_e.hidden}function rt(n,e){if(!n||!Cn.includes(e)||typeof n.setPriority!="function")return!1;try{return n.setPriority(e)!==!1}catch{return!1}}function st({degradedMs:n=Dn,recoveredMs:e=An,holdMs:t=Ln,alpha:i=.1}={}){let r=null,s=0,o=!1;return{feed(a){if(!(a>0)||a>1e3)return null;if(r=r===null?a:r+i*(a-r),o){if(r<e)return o=!1,s=0,"recovered"}else if(s=r>n?s+a:0,s>=t)return o=!0,"degraded";return null},reset(){r=null,s=0,o=!1},get frameMs(){return r},get degraded(){return o}}}function ot({lift:n,max:e=4,log:t=null,options:i=null}={}){let r=i&&typeof i=="object"?i:{},s=new Map,o=null,a=0,l=0,c=(h,d)=>t&&t(h,d),p=(h,d)=>{if(!d.handle)return;let m=Le({id:h,speakerId:o,visible:d.visible});if(m===d.priority)return;d.priority=m;let u=rt(d.handle,m);c("lift-priority",{peer:h,priority:m,applied:u})},f={get size(){return s.size},get max(){return e},set max(h){e=Math.max(0,h|0)},has:h=>s.has(h),handle:h=>s.get(h)&&s.get(h).handle||null,priority:h=>s.get(h)&&s.get(h).priority||null,canAcquire:h=>s.has(h)||s.size<e,acquire(h,d,{wall:m,visible:u=!0,onError:v}={}){let y=s.get(h);if(y)return y.pending||Promise.resolve(y.handle);if(s.size>=e)return Promise.resolve(null);let b=++l,C=Le({id:h,speakerId:o,visible:u}),x={gen:b,handle:null,visible:u,priority:C,pending:null};s.set(h,x);let I={quality:"auto",...r,mode:"live",wall:m,ui:"none",convergence:ve(a),priority:C};return c("lift-acquire",{peer:h,priority:C,convergence:I.convergence}),x.pending=Promise.resolve().then(()=>n(d,I)).then(T=>{if(s.get(h)!==x||x.gen!==b){try{T&&T.remove&&T.remove()}catch{}return null}return x.pending=null,x.handle=T||null,x.priority=null,p(h,x),T&&typeof T.setConvergence=="function"&&T.setConvergence(ve(a)),x.handle},T=>(s.get(h)===x&&s.delete(h),c("lift-failed",{peer:h,message:String(T&&T.message||T).slice(0,200)}),v&&v(T),null)),x.pending},release(h){let d=s.get(h);if(d){if(s.delete(h),d.handle)try{d.handle.remove()}catch{}c("lift-release",{peer:h})}},releaseAll(){for(let h of[...s.keys()])f.release(h)},setSpeaker(h){o=h===void 0?null:h;for(let[d,m]of s)p(d,m)},setVisible(h,d){let m=s.get(h);!m||m.visible===!!d||(m.visible=!!d,p(h,m))},setDepth(h){a=h;let d=ve(h);for(let m of s.values())m.handle&&typeof m.handle.setConvergence=="function"&&m.handle.setConvergence(d);return d},get anyWeb(){for(let h of s.values())if(h.handle&&!h.handle.native)return!0;return!1},list(){return[...s].map(([h,d])=>({id:h,priority:d.priority,pending:!!d.pending,native:!!(d.handle&&d.handle.native)}))}};return f}var Pn=null;function ni(n){Pn=typeof n=="function"?n:null}var Fn=new WeakMap;function ri(n,e){n&&(typeof n=="object"||typeof n=="function")&&Fn.set(n,e)}var jn=Object.freeze({displaySizeM:Object.freeze([.3456,.1944]),displayPixels:Object.freeze([1920,1080]),nominalViewerM:.65,eyeSeparationM:.063});function si(n,e,t=1){let i=jn,r=!!n&&n.displayWidthMeters>0&&n.displayHeightMeters>0&&n.displayPixelWidth>0&&n.displayPixelHeight>0,s=r?[n.displayWidthMeters,n.displayHeightMeters]:[...i.displaySizeM],o=r?[n.displayPixelWidth,n.displayPixelHeight]:[...i.displayPixels],a=(s[0]/o[0]+s[1]/o[1])/2,l=t>0?t:1,c=r?a*l:a*(o[1]/Math.max(1,globalThis.innerHeight||o[1])),p=n?.nominalViewerPosition?.z,f=Number.isFinite(p)&&p>.1;return{canvasSizeM:[(e?.width||0)*c,(e?.height||0)*c],metersPerCssPx:c,displaySizeM:s,nominalViewerM:f?p:i.nominalViewerM,eyeSeparationM:i.eyeSeparationM,source:{size:r?"display":"default",viewer:f?"display":"default",eyeSeparation:"default"}}}var oi=new WeakMap,J;function ai(n){let e=null;for(let[t,i]of n)i>0&&(!e||i<e[1])&&(e=[t,i]);return e}function Wn(n){if(!n||typeof n.getParameter!="function")return null;let e=oi.get(n);if(e)return e;let t,i,r;try{t=n.getParameter(n.MAX_TEXTURE_SIZE??3379),i=n.getParameter(n.MAX_RENDERBUFFER_SIZE??34024),r=n.getParameter(n.MAX_VIEWPORT_DIMS??3386)}catch{return null}let s=r&&r.length>=2?r[0]:0,o=r&&r.length>=2?r[1]:0,a=ai([["MAX_TEXTURE_SIZE",t],["MAX_RENDERBUFFER_SIZE",i],["MAX_VIEWPORT_DIMS",s]]),l=ai([["MAX_TEXTURE_SIZE",t],["MAX_RENDERBUFFER_SIZE",i],["MAX_VIEWPORT_DIMS",o]]);if(!a||!l)return null;let c={maxW:a[1],maxH:l[1],nameW:a[0],nameH:l[0],valueW:a[1],valueH:l[1]};return oi.set(n,c),c}function li(){if(J!==void 0)return J;J=null;try{if(typeof document>"u"||!document||typeof document.createElement!="function")return J;let n=document.createElement("canvas"),e=n.getContext("webgl2")||n.getContext("webgl");if(!e)return J;J=Wn(e),e.getExtension?.("WEBGL_lose_context")?.loseContext?.()}catch{J=null}return J}function ci(n,e,t,{cols:i=2,rows:r=1}={}){let s=n*i,o=e*r,a={eyeW:n,eyeH:e,cols:i,scale:1,clamped:!1,reqW:s,reqH:o,bufW:s,bufH:o,limitName:"",limitValue:0};if(!t||!(n>0)||!(e>0))return a;let l=t.maxW/s,c=t.maxH/o,p=Math.min(l,c);if(!(p<1))return a;let f=l<=c,h=Math.max(1,Math.min(Math.floor(n*p+1e-9),Math.floor(t.maxW/i))),d=Math.max(1,Math.min(Math.floor(e*p+1e-9),Math.floor(t.maxH/r)));return{eyeW:h,eyeH:d,cols:i,scale:p,clamped:!0,reqW:s,reqH:o,bufW:h*i,bufH:d*r,limitName:f?t.nameW:t.nameH,limitValue:f?t.valueW:t.valueH}}function at(n){return Math.round(n*1e3)/1e3}function di(n,e,t){let i=typeof t=="number"?` (renderScale ${at(t)} \u2192 ${at(t*e.scale)})`:` (scale ${at(e.scale)})`;return`${n} ${e.cols===1?"buffer":"SBS buffer"} ${e.reqW}\xD7${e.reqH} exceeds ${e.limitName} ${e.limitValue} on this device; rendering at ${e.bufW}\xD7${e.bufH}${i}.`}function hi(n,e){let t=n?.width||0,i=n?.height||0,r=e&&e.drawingBufferWidth>0?e.drawingBufferWidth:t,s=e&&e.drawingBufferHeight>0?e.drawingBufferHeight:i,o=t>0?r/t:1,a=i>0?s/i:1;return{sx:o,sy:a,w:r,h:s,mismatch:o!==1||a!==1}}function fi(n,e,t,i="laying the eyes out from the drawing buffer. Lower renderScale to stay inside the device limit."){return`${n} the browser clamped this canvas's drawing buffer to ${t.w}\xD7${t.h} (canvas.width/height say ${e.width}\xD7${e.height}); ${i}`}var ne="smoothstep",ct=["linear","smoothstep","easeoutcubic"];function dt(n){if(typeof n!="string")return null;let e=n.toLowerCase().replace(/[-_\s]/g,"");return ct.includes(e)?e:null}function Nn(n,e){if(e<=0)return 0;if(e>=1)return 1;if(n==="linear")return e;if(n==="easeoutcubic"){let t=1-e;return 1-t*t*t}return e*e*(3-2*e)}var ie="idle",ui="rampDownThenFire",lt="fireThenRampUp",Ae=class{constructor(e,t){this._phase=ie,this._targetMode=null,this._firePending=!1,this._fireAtEnd=!1,this._from=0,this._to=0,this._cur=0,this._t=1,this._dur=180/1e3,this._easing=ne,(e!==void 0||t!==void 0)&&this.configure(e,t)}configure(e,t){if(e!==void 0){let i=Number(e);this._dur=Number.isFinite(i)&&i>0?i:0}return t!==void 0&&(this._easing=dt(t)||ne),this}get durationS(){return this._dur}get easing(){return this._easing}request({targetMode:e=null,targetViewCount:t,currentMode:i=null,currentViewCount:r,current:s,steady:o=1}={}){let a=!(t>1),l=!(r>1),c=Number.isFinite(o)?o:1,p=Number.isFinite(s)?s:c;return this._targetMode=e,this._from=p,a&&!l?(this._phase=ui,this._to=0,this._fireAtEnd=!0,this._firePending=!1):!a&&l?(this._phase=lt,this._from=0,this._to=c,this._firePending=!0,this._fireAtEnd=!1):(this._phase=lt,this._to=a?p:c,this._firePending=!(e!==null&&e===i),this._fireAtEnd=!1),this._t=this._dur>0?0:1,this._cur=this._from,this}update(e){let t=!1;if(this._phase!==ie){let i=Number.isFinite(e)&&e>0?e:0;this._t<1&&this._dur>0?(this._t+=i/this._dur,this._t>1&&(this._t=1)):this._t=1,this._cur=this._from+(this._to-this._from)*Nn(this._easing,this._t),this._phase===lt?(this._firePending&&(this._firePending=!1,t=!0),this._t>=1&&(this._phase=ie)):this._t>=1&&(this._fireAtEnd&&(this._fireAtEnd=!1,t=!0),this._phase=ie)}return{factor:this._cur,fire:t,mode:this._targetMode}}active(){return this._phase!==ie}value(){return this._cur}firePending(){return this._phase===ui?this._fireAtEnd:this._firePending}cancel(){return this._phase=ie,this._firePending=!1,this._fireAtEnd=!1,this._t=1,this}};var U=null;ni(n=>{let e=U;if(!e||!e._running||!n)return null;let t=i=>({layer:i.layer,session:e.session});for(let i of e._windows.values())if(i.canvas===n&&i.layer)return t(i);for(let i of e._windows.values())if(i.layer&&typeof n.contains=="function"&&n.contains(i.canvas))return t(i);for(let i of e._windows.values()){let r=i.canvas.parentElement;if(i.layer&&r&&typeof r.contains=="function"&&r.contains(n))return t(i)}return null});var zn=()=>typeof navigator<"u"&&!!navigator.xr,Q=()=>typeof window<"u"&&typeof window.XRDisplayLayer=="function",Oe=()=>Q()&&"excludeElement"in window.XRDisplayLayer.prototype,ht=()=>{if(!Q())return!1;try{return"setViewRig"in window.XRDisplayLayer.prototype}catch{return!1}},Hn=["getDisplayInfo","getRenderingModes","requestRenderingMode"],Si=["renderingmodechange","hardwaredisplaystatechange"],gt="trackingstatechange",Mi=["unknown","tracking","searching"],mi=[...Si,gt];function Ie(n){try{let e=n?n.trackingState:void 0;return Mi.includes(e)?e:null}catch{return null}}var ft=()=>{if(!Q())return!1;try{let n=window.XRDisplayLayer.prototype;return Hn.every(e=>typeof n[e]=="function")}catch{return!1}},ut=()=>{if(!Q())return!1;try{return typeof window.XRDisplayLayer.prototype.undock=="function"}catch{return!1}},se=null;function re(){if(se!==null)return se;if(!Q())return!1;try{let n=window.XRDisplayLayer.occlusionByDrawOrder;if(typeof n=="boolean")return se=n}catch{}return!1}function Vn(n){if(se!==null)return se;if(!n||!Q()||!("occlusionByDrawOrder"in window.XRDisplayLayer.prototype))return null;try{return se=!!n.occlusionByDrawOrder}catch{return null}}var gi=!1;function pt(){gi||(gi=!0,console.info("[inline3d] This browser composites 2D over woven 3D automatically, per-pixel by draw order \u2014 overlay exclusion is obsolete here, so exclude()/addGlobalOverlay()/data-inline3d-overlay/autoChrome are accepted and ignored. Your 2D chrome already occludes the tiles correctly. The calls are harmless (keep them if you also ship to older DisplayXR Browsers); gate on inline3dOcclusionByDrawOrder() to drop them."))}function Ei(){return zn()&&Q()}function mt(n){return{type:"display",position:{x:0,y:0,z:0},orientation:{x:0,y:0,z:0,w:1},virtualDisplayHeight:n.virtualDisplayHeight>0?n.virtualDisplayHeight:.24,ipdFactor:1,parallaxFactor:1,perspectiveFactor:1}}function $n(n,e){let t=Number.isFinite(n.ipdFactor)?n.ipdFactor:1,i=Number.isFinite(n.parallaxFactor)?n.parallaxFactor:1;return{...n,ipdFactor:t*e,parallaxFactor:i*e}}var Un=16;function V(){return typeof performance<"u"&&performance&&typeof performance.now=="function"?performance.now():Date.now()}var Bn=1200,_i=!1;function qn(n){if(n==null)return ne;let e=dt(n);return e||(_i||(_i=!0,console.warn(`[inline3d] createInline3D({ modeSwitch: { easing: ${JSON.stringify(n)} } }) is not a curve this SDK knows (${ct.join(" / ")}); using '${ne}'.`)),ne)}var vi=!1;function Xn(){vi||(vi=!0,console.info("[inline3d] The active rendering mode is 1-view, so this SDK has zeroed every window rig (ipdFactor/parallaxFactor -> 0) \u2014 both eyes now render from one place. The runtime keeps weaving the same two-view atlas whatever the page submits, so leaving stereo in it would put two slightly different images on a flat panel, i.e. a blurry double image instead of 2D. Your rendering is unchanged; the flattening is a copy applied on the way to the layer and it is undone the moment a 2-view mode goes active again."))}function _t(n){return n&&n.detail!==void 0&&n.detail!==null?n.detail:void 0}function ki(n){let e=_t(n);return e!==void 0?[e,n]:[n]}function Gn(n){for(let e of ki(n)){if(typeof e=="number"&&Number.isFinite(e))return e;if(e&&typeof e=="object"){let t=e.modeIndex!==void 0?e.modeIndex:e.mode;if(typeof t=="number"&&Number.isFinite(t))return t}}return-1}function Jn(n){for(let e of ki(n)){if(e==="2d"||e==="3d")return e;if(e&&typeof e=="object"){let t=e.state!==void 0?e.state:e.hardwareDisplayState;if(t==="2d"||t==="3d")return t}}return null}var yi=!1;function Kn(){yi||(yi=!0,console.warn("[inline3d] This browser has no XRDisplayLayer.setViewRig, so the view rig was ignored (the window still weaves \u2014 the runtime keeps the default display rig, scaled by virtualDisplayHeight). Gate on inline3dViewRigSupported() if your page's framing depends on the rig; further calls are silent."))}var wi=!1;function Yn(){wi||(wi=!0,console.warn("[inline3d] addScene got BOTH viewRig and virtualDisplayHeight; on a browser with rig support the rig wins and the height is dropped. They describe the same slot \u2014 virtualDisplayHeight is shorthand for exactly one rig (display, identity pose, all factors 1) \u2014 so there is no merge. This is only worth passing as a PAIR deliberately: the height is what a browser without setViewRig will use, so a camera-rig scene can name its own fallback framing. Otherwise say it once, inside the rig."))}async function Ti(n={}){let{referenceSpace:e="viewer",lazy:t=!0,rootMargin:i="50% 0px",autoChrome:r=!0,modeSwitch:s=null,untrackedFallback:o="none",viewerEase:a}=n;if(!Ei())return{supported:!1,trackingState:"unknown"};let l;try{l=await navigator.xr.requestSession("inline-3d")}catch(p){return{supported:!1,trackingState:"unknown",error:p}}a!==void 0&&ri(l,a);let c=null;try{c=await l.requestReferenceSpace(e)}catch{}return new vt(l,c,{lazy:t,rootMargin:i,autoChrome:r,modeSwitch:s,untrackedFallback:o})}var we=null;function Fe(n={}){return U&&U._running?Promise.resolve(U):we||(we=Ti(n).finally(()=>{we=null}),we)}var bi=.7,Zn=new Set(["IMG","SVG","VIDEO","CANVAS","BUTTON","INPUT","SELECT","TEXTAREA"]);function Qn(n){let e=[],t=document.createTreeWalker(n,NodeFilter.SHOW_ELEMENT);for(let i=t.nextNode();i;i=t.nextNode())if(!i.closest("[data-inline3d-no-overlay]")){if(Zn.has(i.tagName.toUpperCase())){e.push(i);continue}for(let r of i.childNodes)if(r.nodeType===Node.TEXT_NODE&&r.nodeValue.trim()){e.push(i);break}}return e}var er=4;function xi(n){let e=typeof window<"u"&&window.devicePixelRatio||1;return`${n.clientWidth}x${n.clientHeight}@${e}`}var vt=class{constructor(e,t,{lazy:i,rootMargin:r,autoChrome:s=!0,modeSwitch:o=null,untrackedFallback:a="none"}){this.supported=!0,this.session=e,this.refSpace=t,this._windows=new Map,this._globalOverlays=new Set,this._isolatedBy=new WeakMap,this._autoChrome=s,this._autoChromeEls=new Set,this._lastChromeScan=0,this._fullTileWarned=new WeakSet,this._stoodDown=!1,this._activeModeIndex=-1,this._activeViewCount=0,this._hardwareDisplayState=null,this._modes=null,this._stereoCollapsed=!1,this._displayListeners=new Map,this._primedDisplayState=!1;let l=o&&typeof o=="object"?o:{};this._msEnabled=l.enabled!==!1,this._modeSwitch=new Ae((Number.isFinite(l.durationMs)?Math.max(0,l.durationMs):180)/1e3,qn(l.easing)),this._stereoFactor=1,this._msFire=null,this._msArmedUp=!1,this._msLastMs=null,this._msTick=null,this._trackingSupported=Ie(e)!==null,this._trackingState=this._trackingSupported?Ie(e):"unknown",this._untrackedFallback=a==="mono"?"mono":"none",this._bakedStereo=1,this._bakedTarget=1,this._bakedAt=null,this._bakedEaseS=(Number.isFinite(l.durationMs)?Math.max(0,l.durationMs):180)/1e3,this._applyUntrackedTarget(),this.undock=ut()?{model:!1,splat:!1}:null,this._undockRead=!1,this._running=!0,this._lazy=i,this._observer=i&&typeof IntersectionObserver=="function"?new IntersectionObserver(c=>this._onIntersect(c),{rootMargin:r}):null,this._loopId=0,this._framePending=!1,this._frameCount=0,this._frameWatchdog=null,this._suspended=null,U&&U._running&&U!==this&&console.warn("[inline3d] A second inline-3D session is live in this document. The browser's element-rect channel is a whole-widget setter, so both managers clobber each other's rect list every frame \u2014 tiles may flicker, ghost, or weave at a stale rect. Use ONE createInline3D() per document and add every window to it; if you are switching views, close() the previous manager first."),U=this,e.addEventListener("end",()=>this._teardown()),this._bindDisplayEvents(),this._bindTrackingEvents(),this._scanChrome(),this._bindLifecycle(),this._armDprWatch(),this._requestFrame()}get liveCount(){let e=0;for(let t of this._windows.values())t.layer&&e++;return e}addGlobalOverlay(e){if(!(!e||this._globalOverlays.has(e))){re()&&pt(),this._globalOverlays.add(e);for(let t of this._windows.values())t.layer&&this._applyExclusion(t,e)}}removeGlobalOverlay(e){if(!(!e||!this._globalOverlays.delete(e)))for(let t of this._windows.values())t.layer&&this._dropExclusion(t,e)}_scanChrome(){if(re()||!this._autoChrome||!Oe()||typeof document>"u")return;let e=Date.now();if(e-this._lastChromeScan<1e3)return;this._lastChromeScan=e;let t=document.body;if(!t)return;let i=new Set,r=t.querySelectorAll(":scope > *, :scope > * > *, :scope > * > * > *");for(let s of r){if(s.closest("[data-inline3d-no-overlay]"))continue;let o=getComputedStyle(s).position;if(o!=="fixed"&&o!=="sticky")continue;let a=!1;for(let l of this._windows.keys())if(s===l||s.contains(l)){a=!0;break}if(!a){i.add(s);for(let l of Qn(s))i.add(l)}}for(let s of this._autoChromeEls){let o=!1;if(s.isConnected){for(let a of this._windows.keys())if(s===a||s.contains(a)){o=!0;break}}(!s.isConnected||o)&&(this._autoChromeEls.delete(s),this.removeGlobalOverlay(s))}for(let s of i)this._globalOverlays.has(s)||(this._autoChromeEls.add(s),this.addGlobalOverlay(s))}addImage(e,t,i={}){let r=this._register(e,"image",i);return r.ready=ir(t).then(s=>{r.img=s,r.repaint()}),this._handle(e,r)}addVideo(e,t,i={}){let r=this._register(e,"video",i);return r.video=t,this._handle(e,r)}addScene(e,t,i={}){i.viewRig&&i.virtualDisplayHeight!==void 0&&Yn();let r=this._register(e,"scene",{virtualDisplayHeight:.24,...i});return r.onFrame=t,r.ownsBuffer=!1,i.bufferClamped===!0&&(r.warnedBufMismatch=!0),this._handle(e,r)}_handle(e,t){let i=this;return{remove:()=>this._remove(e),exclude:r=>{r&&(re()&&pt(),t.excluded.add(r),this._applyExclusion(t,r))},unexclude:r=>{!r||!t.excluded.delete(r)||this._dropExclusion(t,r)},get trackingState(){return i._trackingState},setViewRig:r=>(t.viewRig=r||null,this._pushViewRig(t)),getDisplayInfo:()=>this._layerCall(t,"getDisplayInfo","getDisplayInfo()"),displayMetrics:async()=>{let r=null;try{r=await this._layerCall(t,"getDisplayInfo","getDisplayInfo()")}catch{}return si(r,e.getBoundingClientRect(),globalThis.devicePixelRatio||1)},getRenderingModes:()=>this._getRenderingModes(t),requestRenderingMode:r=>this._requestRenderingModeEased(r,t),setStereoEnabled:r=>this._setStereoEnabled(r,t),on:(r,s)=>this.on(r,s),off:(r,s)=>this.off(r,s),onDisplayModeChange:r=>this._onDisplayModeChange(r),stats:()=>({frames:t.frames,monoFrames:t.monoFrames}),get firstWoven(){return t.fwPromise},onFirstWoven:r=>{if(typeof r!="function")throw new TypeError("[inline3d] onFirstWoven() takes a function.");let s=!0;return t.fwPromise.then(o=>{if(s)try{r(o)}catch(a){console.error("[inline3d] onFirstWoven callback threw",a)}}),()=>{s=!1}},rewoven:()=>this._rewoven(t)}}getDisplayInfo(){return this._layerCall(this._liveWindow(null),"getDisplayInfo","getDisplayInfo()")}getRenderingModes(){return this._getRenderingModes(null)}requestRenderingMode(e){return this._requestRenderingModeEased(e,null)}setStereoEnabled(e){return this._setStereoEnabled(e,null)}get trackingState(){return this._trackingState}get hardwareDisplayState(){return this._hardwareDisplayState}get activeMode(){return{modeIndex:this._activeModeIndex,viewCount:this._activeViewCount}}get stereoCollapsed(){return this._stereoCollapsed}get modeSwitch(){return{active:this._msTransitionActive(),factor:this._stereoFactor}}close(){try{this.session.end()}catch{}this._teardown()}_effectiveViewRig(e){return this._stereoFactor>=1?e.viewRig||(e.stereoSynthRig?mt(e):null):(e.viewRig||(e.stereoSynthRig=!0),$n(e.viewRig||mt(e),this._stereoFactor))}_setStereoCollapsed(e){let t=!!e;if(this._stereoCollapsed!==t){this._stereoCollapsed=t,t&&Xn(),!t&&this._msArmedUp?(this._msArmedUp=!1,this._startUpRamp()):this._modeSwitch.active()||(this._stereoFactor=t?0:1);for(let i of this._windows.values()){if(t){let r=i.viewRig||mt(i);i.stereoSaved={ipdFactor:r.ipdFactor,parallaxFactor:r.parallaxFactor}}else i.stereoSaved=null;this._pushViewRig(i)}}}_pushViewRig(e){if(!ht())return Kn(),!1;if(!e.layer)return!1;let t=this._effectiveViewRig(e);try{return e.layer.setViewRig(t),!0}catch{return!1}}_layerCall(e,t,i,r=[]){if(!ft())return Promise.reject(new Error(`[inline3d] ${i} needs a DisplayXR Browser with the display-mode API (XRDisplayLayer.getDisplayInfo/getRenderingModes/requestRenderingMode). Gate on inline3dDisplayModesSupported().`));if(!e||!e.layer)return Promise.reject(new Error(`[inline3d] ${i} needs a live weave layer, and this window has none right now (lazy mode closes the layer while the tile is off screen). Call it once the tile is visible, or create the manager with { lazy: false }.`));try{return Promise.resolve(e.layer[t](...r))}catch(s){return Promise.reject(s)}}_liveWindow(e){if(e&&e.layer)return e;for(let t of this._windows.values())if(t.layer)return t;return e||null}async _getRenderingModes(e){let t=await this._layerCall(this._liveWindow(e),"getRenderingModes","getRenderingModes()"),i=Array.isArray(t)?t:[];this._modes=i;let r=i.find(s=>s.isActive);return r&&(this._activeModeIndex=r.modeIndex,this._activeViewCount=r.viewCount,(r.viewCount===1||r.viewCount===2)&&this._setStereoCollapsed(r.viewCount===1)),this._primedDisplayState=!0,t}_requestRenderingMode(e,t){return this._layerCall(this._liveWindow(t),"requestRenderingMode","requestRenderingMode()",[e])}_msTransitionActive(){return this._modeSwitch.active()||this._msArmedUp||this._msFire!==null}async _requestRenderingModeEased(e,t){if(!this._msEnabled||!ht())return this._requestRenderingMode(e,t);let i=this._modes;if(!Array.isArray(i)||i.length===0)try{i=await this._getRenderingModes(t)}catch{i=null}let r=(Array.isArray(i)?i:[]).find(a=>a&&a.modeIndex===e),s=r&&Number.isFinite(r.viewCount)?r.viewCount:0,o=this._activeViewCount;return s<1||s>2||o<1?this._requestRenderingMode(e,t):s===1?o===1?this._requestRenderingMode(e,t):this._rampDownThenRequest(e,t):this._requestThenRampUp(e,t)}_rampDownThenRequest(e,t){if(this._msFire&&this._msFire.modeIndex===e)return this._msFire.promise;this._settlePendingDown("superseded",`a request for mode ${e} replaced it`);let i={modeIndex:e,win:t,resolve:null,reject:null,promise:null};return i.promise=new Promise((r,s)=>{i.resolve=r,i.reject=s}),this._msFire=i,this._modeSwitch.request({targetMode:e,targetViewCount:1,currentMode:this._activeModeIndex,currentViewCount:this._activeViewCount,current:this._stereoFactor,steady:1}),this._msLastMs=V(),this._armModeSwitchTick(),i.promise}_requestThenRampUp(e,t){let r=this._msFire!==null&&e===this._activeModeIndex;this._settlePendingDown("superseded",`a request for mode ${e} reversed it`);let s=r?Promise.resolve(void 0):this._requestRenderingMode(e,t);return this._stereoFactor<1&&(this._stereoCollapsed?(this._msArmedUp=!0,this._modeSwitch.cancel(),this._stereoFactor=0):this._startUpRamp()),s.catch(o=>{throw this._msArmedUp&&(this._msArmedUp=!1,this._modeSwitch.active()||(this._stereoFactor=this._stereoCollapsed?0:1)),o})}_startUpRamp(){this._settlePendingDown("superseded","the display returned to 3D"),this._modeSwitch.request({targetMode:this._activeModeIndex,targetViewCount:2,currentMode:this._activeModeIndex,currentViewCount:2,current:this._stereoFactor,steady:1}),this._msLastMs=V(),this._armModeSwitchTick()}_settlePendingDown(e,t){let i=this._msFire;if(!i)return;this._msFire=null;let r=new Error(`[inline3d] the request for rendering mode ${i.modeIndex} was never forwarded: ${t}. A ->2D switch is held until the disparity has ramped out, so a request that is reversed or replaced in that window is dropped rather than fired late.`);r.name=e,i.reject(r)}_advanceModeSwitch(){if(!this._modeSwitch.active()){this._msLastMs=null,this._disarmModeSwitchTick();return}let e=V(),t=typeof this._msLastMs=="number"?Math.max(0,(e-this._msLastMs)/1e3):0;this._msLastMs=e;let i=this._modeSwitch.update(t);if(i.factor!==this._stereoFactor){this._stereoFactor=i.factor;for(let r of this._windows.values())this._pushViewRig(r)}if(i.fire&&this._msFire){let r=this._msFire;this._msFire=null,this._requestRenderingMode(r.modeIndex,r.win).then(s=>r.resolve(s),s=>{this._startUpRamp(),r.reject(s)})}this._modeSwitch.active()||(this._msLastMs=null,this._disarmModeSwitchTick())}_armModeSwitchTick(){this._msTick!==null||typeof setTimeout!="function"||(this._msTick=setTimeout(()=>{this._msTick=null,this._running&&(this._advanceModeSwitch(),this._modeSwitch.active()&&this._armModeSwitchTick())},Un))}_disarmModeSwitchTick(){this._msTick!==null&&(typeof clearTimeout=="function"&&clearTimeout(this._msTick),this._msTick=null)}async _setStereoEnabled(e,t){let i=e?2:1,r=await this._getRenderingModes(t),s=Array.isArray(r)?r:[],o=s.find(a=>a.viewCount===i&&a.isRequestable);if(!o)throw new Error(`[inline3d] setStereoEnabled(${!!e}) found no requestable ${i}-view mode on this display (${s.length} mode(s) listed). It is sugar over requestRenderingMode() and cannot invent one \u2014 read getRenderingModes() and drive the list yourself.`);return o.isActive&&!this._msTransitionActive()||await this._requestRenderingModeEased(o.modeIndex,t),!!e}_bindDisplayEvents(){let e=this.session;!e||typeof e.addEventListener!="function"||ft()&&(e.addEventListener("renderingmodechange",t=>{this._onRenderingModeChange(t).catch(()=>{})}),e.addEventListener("hardwaredisplaystatechange",t=>{this._onHardwareDisplayStateChange(t).catch(()=>{})}))}_onHardwareDisplayStateChange(e){let t=Jn(e),i=_t(e),r=a=>{a&&(this._hardwareDisplayState=a),this._emitDisplay({type:"hardwaredisplaystatechange",state:a||this._hardwareDisplayState,detail:i})};t&&r(t);let s=this._activeModeIndex,o=this._activeViewCount;return this._getRenderingModes(null).then(a=>{let l=(Array.isArray(a)?a:[]).find(c=>c.isActive)||null;if(l&&(l.modeIndex!==s||l.viewCount!==o)&&this._emitDisplay({type:"renderingmodechange",modeIndex:this._activeModeIndex,viewCount:this._activeViewCount||null,mode:l,detail:null}),!t){let c=l&&typeof l.hardwareDisplay3D=="boolean"?l.hardwareDisplay3D?"3d":"2d":null;r(c)}}).catch(()=>{t||r(null)})}async _onRenderingModeChange(e){let t=_t(e),i=Gn(e),r=null;try{let s=await this._getRenderingModes(null),o=Array.isArray(s)?s:[];r=(i>=0?o.find(a=>a.modeIndex===i):null)||o.find(a=>a.isActive)||null}catch{}r?(this._activeModeIndex=r.modeIndex,this._activeViewCount=r.viewCount):i>=0&&(this._activeModeIndex=i),(this._activeViewCount===1||this._activeViewCount===2)&&this._setStereoCollapsed(this._activeViewCount===1),this._emitDisplay({type:"renderingmodechange",modeIndex:this._activeModeIndex,viewCount:this._activeViewCount||null,mode:r,detail:t})}_emitDisplay(e,t){let i=this._displayListeners.get(e.type);if(!i)return;let r=t||[e];for(let s of[...i])try{s(...r)}catch(o){console.error(`[inline3d] ${e.type} listener threw`,o)}}on(e,t){if(typeof t!="function")throw new TypeError("[inline3d] on() takes (type, function).");if(!mi.includes(e))throw new TypeError(`[inline3d] on() knows ${mi.join(" / ")}, got ${JSON.stringify(e)}.`);let i=this._displayListeners.get(e);return i||this._displayListeners.set(e,i=new Set),i.add(t),()=>this.off(e,t)}off(e,t){let i=this._displayListeners.get(e);i&&i.delete(t)}_onDisplayModeChange(e){if(typeof e!="function")throw new TypeError("[inline3d] onDisplayModeChange() takes a function.");let t=Si.map(i=>this.on(i,e));return()=>{for(let i of t)i()}}async refreshUndock(){if(!ut())return this.undock=null;let e=this._liveWindow(null);if(!e||!e.layer||typeof e.layer.getUndockCapabilities!="function")return this.undock;try{let t=await e.layer.getUndockCapabilities();this.undock={model:!!(t&&t.model),splat:!!(t&&t.splat)}}catch{}return this.undock}_register(e,t,i){this._windows.has(e)&&this._remove(e),e.style.willChange="transform",e.style.transform="translateZ(0)";let r={canvas:e,kind:t,layer:null,img:null,video:null,onFrame:null,onLayerLost:typeof i.onLayerLost=="function"?i.onLayerLost:null,layerLostSent:!1,ready:null,ownsBuffer:t!=="scene",cornerRadius:i.cornerRadius||0,feather:i.feather||0,reqW:i.width||0,reqH:i.height||0,virtualDisplayHeight:i.virtualDisplayHeight||0,viewRig:i.viewRig||null,stereoSaved:null,stereoSynthRig:!1,observeEl:i.observe||e,ctx:t==="scene"?null:e.getContext("2d"),repaint:()=>this._paint(r,null),excluded:new Set,autoExcluded:new Set,overlayObserver:null,sizeObserver:null,resizePending:!1,frames:0,monoFrames:0,fwResult:null,fwResolve:null,fwPromise:null,fwHoldMs:tr(i.firstWovenHoldMs),fwRegAt:V(),fwLayerAt:null,fwStereo:!1,rw:null,rwGone:null};return r.fwPromise=new Promise(s=>{r.fwResolve=s}),this._windows.set(e,r),this._lazy&&this._observer?this._observer.observe(r.observeEl):this._activate(r),r}_remove(e){let t=this._windows.get(e);t&&(this._observer&&this._observer.unobserve(t.observeEl),this._deactivate(t),this._windows.delete(e),this._settleFirstWoven(t,!1,"removed"))}_onIntersect(e){for(let t of e){let i=null;for(let r of this._windows.values())if(r.observeEl===t.target){i=r;break}i&&(t.isIntersecting?this._activate(i):this._deactivate(i))}}_activate(e){if(!e.layer){this._scanChrome();try{let t=ht()?this._effectiveViewRig(e):null,i=t?{viewRig:t}:e.virtualDisplayHeight>0?{virtualDisplayHeight:e.virtualDisplayHeight}:{};e.layer=new XRDisplayLayer(this.session,e.canvas,i)}catch(t){e.layer=null,e.layerFailWarned||(e.layerFailWarned=!0,console.warn("[inline3d] new XRDisplayLayer() failed for this window \u2014 it will show FLAT 2D instead of woven 3D, and the SDK will not retry. The canvas has been repainted mono so it cannot be left holding a raw side-by-side pair.",t)),this._paintMono(e),this._notifyLayerLost(e),this._settleFirstWoven(e,!1,"layer-failed");return}e.fwResult||(e.fwLayerAt=V(),e.fwStereo=!1),this._restartRewoven(e),e.layerLostSent=!1,!this._primedDisplayState&&ft()&&(this._primedDisplayState=!0,this._getRenderingModes(e).catch(()=>{this._primedDisplayState=!1})),ut()&&this.undock&&!this._undockRead&&(this._undockRead=!0,this.refreshUndock().catch(()=>{})),Vn(e.layer)===!0&&this._standDownLegacyOcclusion();for(let t of e.excluded)this._applyExclusion(e,t);for(let t of this._globalOverlays)this._applyExclusion(e,t);this._startOverlayScan(e),e.ownsBuffer&&(this._sizeBuffer(e,!0),this._paint(e,null)),this._startSizeWatch(e)}}_deactivate(e){if(this._stopOverlayScan(e),this._stopSizeWatch(e),e.layer){try{e.layer.close()}catch{}e.layer=null}this._paintMono(e)}_paintMono(e){!e.ownsBuffer||e.kind==="scene"||(this._sizeBuffer(e,!1),this._paint(e,null))}_notifyLayerLost(e){if(!(e.kind!=="scene"||typeof e.onLayerLost!="function"||e.layerLostSent)){e.layerLostSent=!0;try{e.onLayerLost()}catch(t){console.warn("[inline3d] a scene window's onLayerLost callback threw",t)}}}_isFullTileOverlay(e,t){if(!t||typeof t.getBoundingClientRect!="function")return!1;let i=t.getBoundingClientRect(),r=e.canvas.getBoundingClientRect(),s=i.width*i.height,o=r.width*r.height;if(s<=0||o<=0)return!1;let a=Math.min(i.right,r.right)-Math.max(i.left,r.left),l=Math.min(i.bottom,r.bottom)-Math.max(i.top,r.top);if(a<=0||l<=0)return!1;let c=a*l;return c/s<bi||c/o<bi?!1:(this._fullTileWarned.has(t)||(this._fullTileWarned.add(t),console.warn("[inline3d] Refusing a full-tile overlay: this element covers its own woven canvas, and the browser's geometric matcher cannot tell the two apart \u2014 it would stage the CANVAS as the overlay and the tile would show its raw side-by-side buffer instead of 3D. Make the overlay a PARTIAL region of the tile (a caption band, a badge, a corner plate), or move it outside the tile and register it with addGlobalOverlay().",t)),!0)}_applyExclusion(e,t){if(re()||!e.layer||!Oe()||this._isFullTileOverlay(e,t))return;let i=this._isolatedBy.get(t);if(i||(i=new Set,this._isolatedBy.set(t,i)),i.add(e),!t.dataset.inline3dIsolated){t.dataset.inline3dPriorWillChange=t.style.willChange||"";let r=t.style.willChange&&t.style.willChange!=="auto"?t.style.willChange+", transform":"transform";t.style.willChange=r,t.dataset.inline3dIsolated="1"}try{e.layer.excludeElement(t)}catch{}}_dropExclusion(e,t){if(re())return;let i=this._isolatedBy.get(t);if(i&&i.delete(e),(!i||i.size===0)&&this._unpromote(t),!(!e.layer||!Oe()))try{e.layer.unexcludeElement(t)}catch{}}_unpromote(e){return!e||!e.dataset||!e.dataset.inline3dIsolated?!1:(e.style.willChange=e.dataset.inline3dPriorWillChange||"",delete e.dataset.inline3dPriorWillChange,delete e.dataset.inline3dIsolated,!0)}_standDownLegacyOcclusion(){if(this._stoodDown)return;this._stoodDown=!0;let e=!1;for(let t of this._windows.values()){t.overlayObserver&&(this._stopOverlayScan(t),e=!0);for(let i of t.excluded)this._unpromote(i)&&(e=!0)}for(let t of this._autoChromeEls)this._globalOverlays.delete(t),this._unpromote(t),e=!0;this._autoChromeEls.clear();for(let t of this._globalOverlays)this._unpromote(t)&&(e=!0);this._isolatedBy=new WeakMap,e&&pt()}_startOverlayScan(e){if(re()||!Oe()||typeof MutationObserver!="function")return;let t=e.canvas.parentElement;if(!t)return;let i=()=>{let r=new Set(t.querySelectorAll("[data-inline3d-overlay]"));for(let s of e.autoExcluded)r.has(s)||(e.autoExcluded.delete(s),this._dropExclusion(e,s));for(let s of r)e.autoExcluded.has(s)||(e.autoExcluded.add(s),this._applyExclusion(e,s))};i(),e.overlayObserver=new MutationObserver(i),e.overlayObserver.observe(t,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-inline3d-overlay"]})}_stopOverlayScan(e){e.overlayObserver&&(e.overlayObserver.disconnect(),e.overlayObserver=null),e.autoExcluded.clear()}_eyeSize(e,t=!0){let i=Math.min(window.devicePixelRatio||1,2),r=e.reqW||Math.round((e.canvas.clientWidth||256)*i),s=e.reqH||Math.round((e.canvas.clientHeight||256)*i),o=1,a=!e.reqW&&!e.reqH&&this._sourceEyeSize(e);if(a){let c=Math.max(a.w/r,a.h/s);c<1&&(o=c,r=Math.max(1,Math.round(r*c)),s=Math.max(1,Math.round(s*c)))}let l=ci(r,s,li(),{cols:t?2:1});return l.clamped&&(o*=l.scale,r=l.eyeW,s=l.eyeH,e.warnedBufClamp||(e.warnedBufClamp=!0,console.warn(di("[inline3d]",l)))),e.bufScale=o,{w:r,h:s}}_sourceEyeSize(e){if(e.kind!=="video"&&e.kind!=="image")return null;let t=e.kind==="video"?e.video:e.img;if(!t)return null;let i=t.videoWidth||t.naturalWidth||t.width,r=t.videoHeight||t.naturalHeight||t.height;return!(i>1)||!(r>0)?null:{w:i/2,h:r}}_checkSceneBuffer(e){let t=e.canvas;if(!t||typeof t.getContext!="function")return;if(e.sceneGl===void 0){let r=null;try{r=t.getContext("webgl2")||t.getContext("webgl")}catch{r=null}e.sceneGl=r&&typeof r.drawingBufferWidth=="number"?r:null}if(!e.sceneGl)return;let i=hi(t,e.sceneGl);i.mismatch&&(e.warnedBufMismatch=!0,console.warn(fi("[inline3d]",t,i,"getViewport() splits canvas.width, so the eyes are off-centre in the woven buffer. This scene canvas is sized by the page: keep 2 \xD7 eye width and the height within MAX_TEXTURE_SIZE / MAX_RENDERBUFFER_SIZE / MAX_VIEWPORT_DIMS, or map getViewport() onto gl.drawingBufferWidth/Height.")))}_sizeBuffer(e,t){let{w:i,h:r}=this._eyeSize(e,t);e.eyeW=i,e.eyeH=r,e.canvas.width=t?i*2:i,e.canvas.height=r,e.sbs=t}_startSizeWatch(e){typeof ResizeObserver=="function"&&(e.sizeObserver||!e.ownsBuffer||e.reqW&&e.reqH||(e.sizeObserver=new ResizeObserver(()=>this._onBoxChange(e)),e.sizeObserver.observe(e.canvas)))}_stopSizeWatch(e){e.sizeObserver&&(e.sizeObserver.disconnect(),e.sizeObserver=null),e.resizePending=!1}_onBoxChange(e){if(!e.layer||!e.ownsBuffer||e.resizePending)return;e.resizePending=!0;let t=()=>{if(!e.resizePending||(e.resizePending=!1,!e.layer||!e.ownsBuffer))return;this._noteRewovenBox(e);let{w:i,h:r}=this._eyeSize(e);i===e.eyeW&&r===e.eyeH||(this._sizeBuffer(e,!0),this._paint(e,null))};typeof requestAnimationFrame=="function"?requestAnimationFrame(t):t()}_armDprWatch(){if(typeof window>"u"||typeof window.matchMedia!="function")return;this._disarmDprWatch();let e;try{e=window.matchMedia(`(resolution: ${window.devicePixelRatio||1}dppx)`)}catch{return}let t=()=>{if(this._running){this._armDprWatch();for(let i of this._windows.values())i.layer&&this._onBoxChange(i)}};try{e.addEventListener("change",t)}catch{return}this._dprWatch={q:e,onChange:t}}_disarmDprWatch(){if(this._dprWatch){try{this._dprWatch.q.removeEventListener("change",this._dprWatch.onChange)}catch{}this._dprWatch=null}}_paint(e,t){if(e.kind==="scene"||!e.ctx)return;let i=this._running&&!!e.layer;!i&&e.sbs&&this._sizeBuffer(e,!1);let r=e.kind==="video"?e.video:e.img;if(!r)return;if(e.kind==="video"&&(r.readyState||0)<2){i&&this._recommitLastFrame(e);return}let s=e.canvas,o=e.ctx,a=r.videoWidth||r.naturalWidth||r.width,l=r.videoHeight||r.naturalHeight||r.height;if(!a||!l)return;let c=a+"x"+l;if(e.srcKey!==c&&(e.srcKey=c,e.ownsBuffer&&!(e.reqW&&e.reqH))){let{w:u,h:v}=this._eyeSize(e,e.sbs);(u!==e.eyeW||v!==e.eyeH)&&this._sizeBuffer(e,e.sbs)}let p=e.bufScale||1,f=e.cornerRadius*p,h=e.feather*p;if(o.clearRect(0,0,s.width,s.height),!e.sbs){Pe(o,r,0,0,a/2,l,0,0,s.width,s.height,f,h);return}let d=s.width/2,m=Math.min(this._stereoFactor,this._bakedStereo);if(m<1){Pe(o,r,0,0,a/2,l,0,0,d,s.height,f,h),nr(o,r,a/2,l,d,s.height,m,f,h);return}f>0||h>0?(Pe(o,r,0,0,a/2,l,0,0,d,s.height,f,h),Pe(o,r,a/2,0,a/2,l,d,0,d,s.height,f,h)):o.drawImage(r,0,0,a,l,0,0,s.width,s.height)}_bindTrackingEvents(){let e=this.session;!e||typeof e.addEventListener!="function"||this._trackingSupported&&e.addEventListener(gt,()=>{this._setTrackingState(Ie(e)||"unknown")})}_setTrackingState(e){let t=Mi.includes(e)?e:"unknown";if(t===this._trackingState)return;this._trackingState=t,this._applyUntrackedTarget();let i={type:gt,state:t};this._emitDisplay(i,[t,i])}_applyUntrackedTarget(){if(this._untrackedFallback!=="mono"){this._bakedTarget=1;return}this._trackingState==="searching"?this._bakedTarget=0:this._trackingState==="tracking"&&(this._bakedTarget=1)}_trackBakedStereo(e){this._trackingSupported&&this._setTrackingState(Ie(this.session)||"unknown");let t=this._bakedAt===null||!Number.isFinite(e)?0:Math.max(0,(e-this._bakedAt)/1e3);this._bakedAt=Number.isFinite(e)?e:this._bakedAt;let i=this._bakedStereo,r=this._bakedTarget;if(i===r)return;let s=this._bakedEaseS>0?t/this._bakedEaseS:1;this._bakedStereo=r>i?Math.min(r,i+s):Math.max(r,i-s)}_recommitLastFrame(e){let t=e.canvas;if(!t.width||!t.height)return;let i=e.ctx;try{i.save(),i.globalCompositeOperation="copy",i.drawImage(t,0,0),i.restore()}catch{}}_requestFrame(e){if(!this._running||this._framePending&&!e)return;let t=e?++this._loopId:this._loopId;this._framePending=!0;try{this.session.requestAnimationFrame((i,r)=>{t===this._loopId&&(this._framePending=!1,this._frameCount++,this._frame(i,r))})}catch{this._framePending=!1}}_frame(e,t){if(!this._running)return;this._requestFrame(),this._advanceModeSwitch();let i=this.refSpace?t.getViewerPose(this.refSpace):null,r=i?i.views:null;this._trackBakedStereo(e);for(let s of this._windows.values())if(s.layer){if(s.kind==="scene"){if(r&&s.onFrame){if(s.frames++,r.length<2&&(s.monoFrames++,s.monoFrames%300===1&&typeof console<"u"&&console.debug)){let o=(100*s.monoFrames/Math.max(1,s.frames)).toFixed(1);console.debug(`[inline3d] scene window: ${s.monoFrames} non-stereo view lists in ${s.frames} frames (${o}%). The viewer replays its last good stereo frame for these; a rising rate means the session is falling back under load.`)}try{s.onFrame(r,s.layer,t),r.length>=2&&(s.fwStereo=!0,s.warnedBufMismatch||this._checkSceneBuffer(s),s.rw&&(s.rw.stereo=!0))}catch(o){s.frameThrewWarned||(s.frameThrewWarned=!0,console.warn("[inline3d] a scene window's onFrame threw; this window will keep whatever it last drew, and the other windows carry on. Further throws from it are silent.",o))}}}else this._paint(s,r),s.sbs&&(s.kind==="video"?(s.video&&s.video.readyState||0)>=2:s.img)&&(s.fwStereo=!0,s.rw&&(s.rw.stereo=!0));this._tickFirstWoven(s)}}_tickFirstWoven(e){if(e.rw){this._noteRewovenBox(e);let t=e.rw,i=V();t.stereo&&i-t.at>=e.fwHoldMs?this._settleRewoven(e,!0,"hold-elapsed"):t.at>t.calledAt&&i-t.calledAt>=er*e.fwHoldMs&&this._settleRewoven(e,!0,"hold-capped")}e.fwResult||!e.fwStereo||e.fwLayerAt===null||V()-e.fwLayerAt<e.fwHoldMs||this._settleFirstWoven(e,!0,"hold-elapsed")}_settleFirstWoven(e,t,i){t||(e.rwGone||(e.rwGone=i),this._settleRewoven(e,!1,i)),!e.fwResult&&(e.fwResult=Object.freeze({woven:t,confirmed:!1,reason:i,ms:Math.round(V()-e.fwRegAt)}),e.fwResolve(e.fwResult),e.fwResolve=null)}_rewoven(e){if(!e.fwResult)return e.fwPromise;if(!e.fwResult.woven)return Promise.resolve(e.fwResult);if(e.rwGone)return Promise.resolve(Object.freeze({woven:!1,confirmed:!1,reason:e.rwGone,ms:0}));if(e.rw)return this._restartRewoven(e),e.rw.promise;let t,i=new Promise(s=>{t=s}),r=V();return e.rw={promise:i,resolve:t,calledAt:r,at:r,stereo:!1,box:xi(e.canvas)},i}_noteRewovenBox(e){let t=e.rw;if(!t)return;let i=xi(e.canvas);i!==t.box&&(t.box=i,this._restartRewoven(e))}_restartRewoven(e){e.rw&&(e.rw.at=V(),e.rw.stereo=!1)}_settleRewoven(e,t,i){let r=e.rw;r&&(e.rw=null,r.resolve(Object.freeze({woven:t,confirmed:!1,reason:i,ms:Math.round(V()-r.calledAt)})))}_bindLifecycle(){typeof window>"u"||(this._onPageHide=()=>this._suspend(),this._onPageShow=e=>this._resume(!!(e&&e.persisted)),window.addEventListener("pagehide",this._onPageHide),window.addEventListener("pageshow",this._onPageShow),typeof document<"u"&&"onfreeze"in document&&(this._onFreeze=()=>this._suspend(),this._onResume=()=>this._resume(!0),document.addEventListener("freeze",this._onFreeze),document.addEventListener("resume",this._onResume)))}_unbindLifecycle(){typeof window>"u"||(this._onPageHide&&window.removeEventListener("pagehide",this._onPageHide),this._onPageShow&&window.removeEventListener("pageshow",this._onPageShow),this._onFreeze&&typeof document<"u"&&(document.removeEventListener("freeze",this._onFreeze),document.removeEventListener("resume",this._onResume)),this._onPageHide=this._onPageShow=this._onFreeze=this._onResume=null,this._frameWatchdog&&(clearTimeout(this._frameWatchdog),this._frameWatchdog=null))}_suspend(){if(!this._running||this._suspended)return;let e=[];for(let t of this._windows.values())t.layer&&(e.push(t),this._deactivate(t));this._suspended=e}_resume(e){if(!this._running)return;let t=this._suspended;if(this._suspended=null,t)for(let i of t)this._windows.has(i.canvas)&&(this._lazy&&this._observer?(this._observer.unobserve(i.observeEl),this._observer.observe(i.observeEl)):this._activate(i));this._lastChromeScan=0,this._scanChrome(),this._armDprWatch(),e&&this._watchForStalledFrames()}_watchForStalledFrames(){if(this._frameWatchdog||typeof setTimeout!="function")return;let e=this._frameCount;this._frameWatchdog=setTimeout(()=>{this._frameWatchdog=null,!(!this._running||this._frameCount!==e)&&this._requestFrame(!0)},1e3)}_teardown(){if(this._running){this._running=!1,U===this&&(U=null),this._unbindLifecycle(),this._disarmDprWatch(),this._disarmModeSwitchTick(),this._modeSwitch.cancel(),this._msArmedUp=!1,this._settlePendingDown("closed","the inline-3D session closed first"),this._observer&&this._observer.disconnect();for(let e of this._windows.values()){if(this._stopOverlayScan(e),this._stopSizeWatch(e),e.layer){try{e.layer.close()}catch{}e.layer=null}this._paintMono(e),this._notifyLayerLost(e),this._settleFirstWoven(e,!1,"session-ended")}this._windows.clear(),this._setTrackingState("unknown"),this._displayListeners.clear()}}};function tr(n){return typeof n=="number"&&Number.isFinite(n)&&n>=0?n:Bn}function ir(n){return typeof n!="string"?Promise.resolve(n):new Promise((e,t)=>{let i=new Image;i.decoding="async",i.onload=()=>e(i),i.onerror=t,i.src=n})}function Pe(n,e,t,i,r,s,o,a,l,c,p,f){p>0&&n.roundRect?(n.save(),n.beginPath(),n.roundRect(o,a,l,c,p),n.clip(),n.drawImage(e,t,i,r,s,o,a,l,c),n.restore()):n.drawImage(e,t,i,r,s,o,a,l,c),f>0&&Ci(n,o,a,l,c,f)}function nr(n,e,t,i,r,s,o,a,l){n.save(),a>0&&n.roundRect&&(n.beginPath(),n.roundRect(r,0,r,s,a),n.clip()),n.drawImage(e,0,0,t,i,r,0,r,s),o>0&&(n.globalAlpha=o,n.drawImage(e,t,0,t,i,r,0,r,s)),n.restore(),l>0&&Ci(n,r,0,r,s,l)}function Ci(n,e,t,i,r,s){let o=Math.min(s,Math.floor(Math.min(i,r)/2));if(o<=0)return;n.save(),n.globalCompositeOperation="destination-out";let a=[[e,t,i,o,[e,t],[e,t+o]],[e,t+r-o,i,o,[e,t+r],[e,t+r-o]],[e,t,o,r,[e,t],[e+o,t]],[e+i-o,t,o,r,[e+i,t],[e+i-o,t]]];for(let[l,c,p,f,h,d]of a){let m=n.createLinearGradient(h[0],h[1],d[0],d[1]);m.addColorStop(0,"rgba(0,0,0,1)"),m.addColorStop(1,"rgba(0,0,0,0)"),n.fillStyle=m,n.fillRect(l,c,p,f)}n.restore()}function oe(n,e){return n>0&&e>0&&n/e>2.5}function X(n,e,t,i,r){let s=Math.abs(i||0),o=Math.min(n-2*s,e*t);o=Math.max(1,o);let a=Math.min(e,o/t);o=a*t;let l=(n-o)/2+(r===0?i:-i);return{sx:Math.max(0,Math.min(n-o,l)),sy:(e-a)/2,sw:o,sh:a}}function be(n,e,t){let i=Math.min(n,e*t),r=i/t;return{w:Math.max(2,Math.round(i/2)*2),h:Math.max(2,Math.round(r/2)*2)}}function ae(n,e){let t=n/2;return[{src:"R",sx:t,sw:t,sy:0,sh:e,dx:0,dw:t,mirror:!0},{src:"L",sx:0,sw:t,sy:0,sh:e,dx:t,dw:t,mirror:!0}]}function yt(n,e,t){let i=new n.constructor(n.length);for(let r of ae(e,t))for(let s=0;s<t;s++)for(let o=0;o<r.dw;o++){let a=r.sx+(r.sw-1-o);i[s*e+r.dx+o]=n[s*e+a]}return i}function Ri(n,e){return!(n>0)||!(e>0)||e>=180?null:n/2/Math.tan(e/2*Math.PI/180)}function je({eyeWidthPx:n,hfovDeg:e,baselineMm:t,subjectZmm:i}){let r=Ri(n,e);return r===null||!(t>0)||!(i>0)?0:r*t/(2*i)}function We(n,e,t=.12){let i=Math.max(0,e*t);return Math.max(-i,Math.min(i,n||0))}function Ne(n,e,t=.2){let i=n+t*(e-n);return Math.abs(e-i)<.05?e:i}function xe(){let n={hello:null,subjectZmm:null,measuredPx:null,depth:0,current:0,target(e){let t=n.measuredPx!==null?n.measuredPx/2:n.hello&&n.subjectZmm?je({eyeWidthPx:e,hfovDeg:n.hello.hfovDeg,baselineMm:n.hello.baselineMm,subjectZmm:n.subjectZmm}):0;return We(t+n.depth*.05*e,e)},step(e){return n.current=Ne(n.current,n.target(e)),n.current}};return n}var ze=1,wt="inline3d-call/1",Di=Object.freeze(["sbs","mono"]),le=4,Li=4,bt=5,rr=150,sr=5e3,or=/^[A-Za-z0-9_-]{16,64}$/,ar=16;function xt(n){let e=new Uint8Array(ar);return(n||(i=>globalThis.crypto.getRandomValues(i)))(e),Oi(e)}function Ai(n){let e=new Uint8Array(8);return(n||(i=>globalThis.crypto.getRandomValues(i)))(e),Oi(e)}function Oi(n){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",t="",i=0;for(;i+2<n.length;i+=3){let s=n[i]<<16|n[i+1]<<8|n[i+2];t+=e[s>>18&63]+e[s>>12&63]+e[s>>6&63]+e[s&63]}let r=n.length-i;if(r===1){let s=n[i]<<16;t+=e[s>>18&63]+e[s>>12&63]}else if(r===2){let s=n[i]<<16|n[i+1]<<8;t+=e[s>>18&63]+e[s>>12&63]+e[s>>6&63]}return t}function ce(n){return typeof n=="string"&&or.test(n)}function Se(n){if(!n)return null;let e="";if(typeof n=="object")e=n.hash||n.href&&String(n.href).split("#")[1]||"";else{let t=String(n),i=t.indexOf("#");e=i>=0?t.slice(i+1):t.includes("=")&&!t.includes("://")?t:""}e=e.replace(/^#/,"");for(let t of e.split("&")){let i=t.indexOf("=");if(i<0||decodeURIComponent(t.slice(0,i))!=="room")continue;let r=decodeURIComponent(t.slice(i+1));return ce(r)?r:null}return null}function He(n,e){if(!ce(e))throw new Error(`@displayxr/inline3d/call: invalid room id "${e}"`);return`${String(n||"").split("#")[0]}#room=${e}`}function St(n){if(!n||typeof n!="object"||n.type!=="hello")return null;let e=(t,i,r)=>typeof t=="number"&&Number.isFinite(t)&&t>=i&&t<=r?t:null;return{type:"hello",v:typeof n.v=="number"?n.v:ze,format:Di.includes(n.format)?n.format:"mono",width:e(n.width,1,16384),height:e(n.height,1,16384),baselineMm:e(n.baselineMm,1,1e3),hfovDeg:e(n.hfovDeg,5,170),rectified:n.rectified===!0,sdk:typeof n.sdk=="string"?n.sdk.slice(0,64):null}}function Mt({format:n,width:e,height:t,baselineMm:i,hfovDeg:r,rectified:s}={}){let o={type:"hello",v:ze,format:Di.includes(n)?n:"mono",width:e||0,height:t||0,rectified:!!s,sdk:wt};return Number.isFinite(i)&&(o.baselineMm=i),Number.isFinite(r)&&(o.hfovDeg=r),o}function Et(n){if(!n||n.type!=="hint")return null;let e=n.subjectZmm;return typeof e=="number"&&Number.isFinite(e)&&e>=rr&&e<=sr?{type:"hint",subjectZmm:e}:null}function Ii(n){return!n||n.type!=="state"?null:{type:"state",muted:n.muted===!0,cameraOff:n.cameraOff===!0,speaking:n.speaking===!0}}function kt(n){let e=1e3/n,t=-1/0;return i=>i-t<e?!1:(t=i,!0)}function Tt({format:n,woven:e,mono3D:t="auto",lift:i=!1,overBudget:r=!1,failed:s=!1}){return(n==="sbs"?"sbs":"mono")==="sbs"?{route:e?"woven-sbs":"flat-left"}:e?t==="off"||t===!1?{route:"flat",mono3d:"off"}:i?s?{route:"flat",mono3d:"failed"}:r?{route:"flat",mono3d:"budget"}:{route:"lifted",mono3d:"lifted"}:{route:"flat",mono3d:"unavailable"}:{route:"flat"}}function Ct(n){return n==="woven-sbs"?"3D":n==="lifted"?"2D\u21923D":"2D"}function Rt({need:n=10,needNoPose:e=30}={}){let t=0,i=0,r=!1;return{feed(s){return r?!0:(i++,s===null?r=i>=e:(t=s>=1?t+1:0,r=t>=n),r)},get live(){return r}}}function Ve(n,e){let t=Math.max(1,e|0),r=n==="sbs"?[6e3,4e3,3e3]:[2500,1800,1400];return r[Math.min(t,r.length)-1]}function B(n,{baseMs:e=1e3,maxMs:t=3e4,rand:i=Math.random}={}){let r=Math.min(t,e*Math.pow(2,Math.max(0,n)));return Math.round(r*(.8+.4*i()))}var Me=Object.freeze(["VP9","VP8","AV1"]);function cr(n,e=Me){let t=e.indexOf(String(n||"").toUpperCase());return t<0?e.length:t}function $e(n,e=Me){let t=i=>cr(String(i.mimeType||"").split("/")[1],e);return n.map((i,r)=>({c:i,i:r,r:t(i)})).sort((i,r)=>i.r-r.r||i.i-r.i).map(i=>i.c)}function Ee(n,e=Me){if(!n)return n;let t=n.includes(`\r
|
|
3
3
|
`)?`\r
|
|
4
4
|
`:`
|
|
5
|
-
`,i=n.split(t),r=i.findIndex(d=>d.startsWith("m=video"));if(r<0)return n;let s=i.findIndex((d,m)=>m>r&&d.startsWith("m="));s<0&&(s=i.length);let o=i.slice(r,s),a=new Map,l=new Map;for(let d of o){let m=d.match(/^a=rtpmap:(\d+) ([\w-]+)\//);m&&a.set(m[1],m[2].toUpperCase());let u=d.match(/^a=fmtp:(\d+) apt=(\d+)/);u&&(l.has(u[2])||l.set(u[2],[]),l.get(u[2]).push(u[1]))}let c=i[r].split(" "),p=c.slice(3),f=[];for(let d of e)for(let m of p)if(a.get(m)===d&&!f.includes(m)){f.push(m);for(let u of l.get(m)||[])p.includes(u)&&!f.includes(u)&&f.push(u)}if(!f.length)return n;let h=p.filter(d=>!f.includes(d));return i[r]=[...c.slice(0,3),...f,...h].join(" "),i.join(t)}var Pi=Object.freeze([{urls:"stun:stun.l.google.com:19302"}]),hr=4e3,fr=1e4,ur=2e4,pr=8e3,mr=1e4;function Te(n){let e=Number.isInteger(n)?n:ae;return Math.max(2,Math.min(Li,e))}function Fi(n,e){return n<e}var ke=class{constructor({signaling:e,id:t,maxPeers:i,iceServers:r,RTCPeerConnection:s,log:o,unreachableMs:a}={}){this.unreachableMs=a>0?a:mr,this.signaling=e,this.id=t,this.maxPeers=Te(i),this.pageIce=r||null,this.iceServers=r||Pi,this.PC=s||globalThis.RTCPeerConnection,this.log=o||(()=>{}),this.peers=new Map,this.session=null,this.ready=!1,this._pending=[],this.stopped=!1,this.sendFormat="mono",this.localStream=null}get size(){return this.peers.size}async start({room:e,localStream:t,sendFormat:i,onPeer:r,onPeerLeft:s,onStream:o,onMessage:a,onPeerState:l,onRefused:c,onSignalingState:p,onGhost:f}){this.localStream=t,this.sendFormat=i||"mono",this.cb={onPeer:r,onPeerLeft:s,onStream:o,onMessage:a,onPeerState:l,onRefused:c,onSignalingState:p,onGhost:f};let h=u=>(...v)=>this.ready?u(...v):this._pending.push(()=>u(...v));this.session=await this.signaling.join(e,{id:this.id,maxPeers:this.maxPeers,onPeerJoined:h(u=>this._onPeerJoined(u)),onPeerLeft:h(u=>this._onPeerLeftSignaling(u)),onSignal:h((u,v)=>this._onSignal(u,v)),onDisconnect:u=>p?.(u?"closed":"reconnecting",u),onPeerUnreachable:h(u=>f?.(u,!0)),onPeerReachable:h(u=>f?.(u,!1)),onReconnect:h(u=>{p?.("connected");for(let v of u)this._onPeerJoined(v)})}),!this.pageIce&&this.session.iceServers&&this.session.iceServers.length&&(this.iceServers=[...Pi,...this.session.iceServers]);let d=this.session.peers||[];if(d.length>=this.maxPeers){this.session.leave();let u=new Error(`@displayxr/inline3d/call: this call is full (${this.maxPeers} participants)`);throw u.code="room-full",u}this.ready=!0;for(let u of d)this._onPeerJoined(u);let m=this._pending;this._pending=[];for(let u of m)u();return this.session}_onPeerJoined(e){if(this.stopped||e===this.id)return;let t=this.peers.get(e);if(t){t.absent=!1,t.state!=="connected"&&Fi(this.id,e)&&this._rebuild(t,"rejoined");return}if(this.peers.size>=this.maxPeers-1){this.log("refused",{peer:e,reason:"maxPeers",maxPeers:this.maxPeers}),this.cb.onRefused?.(e);return}let i=this._newRecord(e);this.cb.onPeer?.(e),i.offerer?this._build(i,1):i.waitTimer=setTimeout(()=>this._askRestart(i),pr)}_onPeerLeftSignaling(e){let t=this.peers.get(e);t&&(t.absent=!0,t.state!=="connected"&&this._drop(t,"left"))}_newRecord(e){let t={id:e,offerer:Fi(this.id,e),pc:null,builtAt:0,offerAt:0,dc:null,gen:0,state:"new",stream:null,attempts:0,iceRestarted:!1,absent:!1,pendingCandidates:[],timers:new Set,waitTimer:null,unreachable:!1,unreachTimer:null};return this.peers.set(e,t),this._armUnreachable(t),t}_build(e,t){this._closePc(e),e.gen=t,e.builtAt=Date.now(),e.iceRestarted=!1,e.pendingCandidates=[],e.stream=null;let i=new this.PC({iceServers:this.iceServers});e.pc=i;let r=i.createDataChannel("dxr-call",{negotiated:!0,id:0,ordered:!0});if(this._wireDc(e,r),e.offerer){let s=this.localStream?this.localStream.getTracks():[],o=s.find(p=>p.kind==="audio"),a=s.find(p=>p.kind==="video"),l=this.localStream?[this.localStream]:[];i.addTransceiver(o||"audio",{direction:"sendrecv",streams:l});let c=i.addTransceiver(a||"video",{direction:"sendrecv",streams:l});this._preferCodecs(c)}return i.onicecandidate=s=>{s.candidate&&this._signal(e,{kind:"candidate",candidate:s.candidate.toJSON?s.candidate.toJSON():s.candidate})},i.ontrack=s=>{if(e.stream||(e.stream=new MediaStream),!e.stream.getTracks().includes(s.track)){for(let o of e.stream.getTracks())o.kind===s.track.kind&&e.stream.removeTrack(o);e.stream.addTrack(s.track)}this.cb.onStream?.(e.id,e.stream)},i.onconnectionstatechange=()=>this._onConnState(e,i),this._arm(e,ur,()=>{e.pc===i&&i.connectionState!=="connected"&&this._fail(e,"connect-timeout")}),e.offerer&&this._offer(e).catch(s=>this.log("offer-error",{peer:e.id,err:String(s)})),this._setState(e,e.attempts>0?"reconnecting":"connecting"),i}async _offer(e,{iceRestart:t=!1}={}){let i=e.pc,r=await i.createOffer(t?{iceRestart:!0}:void 0);this._canPreferCodecs||(r.sdp=Ee(r.sdp)),await i.setLocalDescription(r),this._signal(e,{kind:"offer",sdp:i.localDescription.sdp})}async _onSignal(e,t){if(this.stopped||!t||typeof t!="object")return;let i=this.peers.get(e);if(!i&&(t.kind!=="offer"||(this._onPeerJoined(e),i=this.peers.get(e),!i)))return;let r=t.gen|0;try{switch(t.kind){case"offer":{if(i.offerer||(clearTimeout(i.waitTimer),r<i.gen))return;i.offerAt=Date.now(),(r>i.gen||!i.pc)&&this._build(i,r);let s=i.pc;await s.setRemoteDescription({type:"offer",sdp:t.sdp}),this._attachAnswererTracks(i);let o=await s.createAnswer();this._canPreferCodecs||(o.sdp=Ee(o.sdp)),await s.setLocalDescription(o),this._signal(i,{kind:"answer",sdp:s.localDescription.sdp}),this._flushCandidates(i);break}case"answer":if(!i.offerer||r!==i.gen||!i.pc||i.pc.signalingState!=="have-local-offer")return;await i.pc.setRemoteDescription({type:"answer",sdp:t.sdp}),this._flushCandidates(i);break;case"candidate":if(r!==i.gen||!i.pc)return;i.pc.remoteDescription?await i.pc.addIceCandidate(t.candidate).catch(()=>{}):i.pendingCandidates.push(t.candidate);break;case"restart":if(!i.offerer||i.pc&&i.state!=="connected"&&Date.now()-i.builtAt<5e3)return;this._rebuild(i,"peer-asked");break;case"bye":this._drop(i,"left");break}}catch(s){this.log("signal-error",{peer:e,kind:t.kind,err:String(s)})}}_flushCandidates(e){let t=e.pendingCandidates;e.pendingCandidates=[];for(let i of t)e.pc.addIceCandidate(i).catch(()=>{})}_attachAnswererTracks(e){let t=e.pc,i=this.localStream?this.localStream.getTracks():[];for(let r of t.getTransceivers()){let s=r.receiver&&r.receiver.track?r.receiver.track.kind:null;if(!s||r.sender.track)continue;let o=i.find(a=>a.kind===s);o&&(r.sender.replaceTrack(o).catch(()=>{}),this.localStream&&r.sender.setStreams&&r.sender.setStreams(this.localStream)),r.direction="sendrecv",s==="video"&&this._preferCodecs(r)}}_preferCodecs(e){let t=globalThis.RTCRtpReceiver&&RTCRtpReceiver.getCapabilities&&RTCRtpReceiver.getCapabilities("video");if(this._canPreferCodecs=!!(e&&e.setCodecPreferences&&t),!!this._canPreferCodecs)try{e.setCodecPreferences($e(t.codecs))}catch{this._canPreferCodecs=!1}}_onConnState(e,t){if(e.pc!==t)return;let i=t.connectionState;this.log("pc-state",{peer:e.id,state:i,gen:e.gen}),i==="connected"?(this._clearTimers(e),e.attempts=0,e.iceRestarted=!1,this._setState(e,"connected"),this.tuneSenders()):i==="disconnected"?(this._setState(e,"reconnecting"),this._arm(e,hr,()=>{e.pc===t&&t.connectionState!=="connected"&&this._fail(e,"disconnected")})):i==="failed"?this._fail(e,"failed"):i==="closed"&&!this.stopped&&this.peers.get(e.id)===e&&this._fail(e,"closed")}_fail(e,t){if(this.stopped||this.peers.get(e.id)!==e)return;if(e.absent)return this._drop(e,"left");if(this._setState(e,"reconnecting"),!e.offerer)return this._askRestart(e);let i=e.pc;if(i&&!e.iceRestarted&&i.connectionState!=="closed"&&i.signalingState!=="closed"){e.iceRestarted=!0,this.log("ice-restart",{peer:e.id,why:t,gen:e.gen}),this._offer(e,{iceRestart:!0}).catch(()=>this._rebuild(e,"ice-restart-failed")),this._arm(e,fr,()=>{e.pc===i&&i.connectionState!=="connected"&&this._rebuild(e,"ice-restart-timeout")});return}this._rebuild(e,t)}_rebuild(e,t){if(this.stopped||this.peers.get(e.id)!==e)return;this._clearTimers(e),this._closePc(e),this._setState(e,"reconnecting");let i=B(e.attempts++);this.log("redial",{peer:e.id,why:t,attempt:e.attempts,inMs:i}),this._arm(e,i,()=>this._build(e,e.gen+1))}_askRestart(e){if(this.stopped||this.peers.get(e.id)!==e||e.offerer)return;let t=Date.now();this._signal(e,{kind:"restart"}),this._arm(e,Math.max(3e3,B(e.attempts++)),()=>{e.state!=="connected"&&!(e.offerAt>=t)&&this._askRestart(e)})}_drop(e,t){this.peers.get(e.id)===e&&(this._clearTimers(e),clearTimeout(e.unreachTimer),clearTimeout(e.waitTimer),this._closePc(e),this.peers.delete(e.id),this._setState(e,"left"),this.cb.onPeerLeft?.(e.id,t),this.tuneSenders())}_closePc(e){if(e.dc){try{e.dc.close()}catch{}e.dc=null}if(e.pc){let t=e.pc;e.pc=null;try{t.close()}catch{}}}_arm(e,t,i){let r=setTimeout(()=>{e.timers.delete(r),i()},t);e.timers.add(r)}_clearTimers(e){for(let t of e.timers)clearTimeout(t);e.timers.clear()}_armUnreachable(e){e.unreachTimer||e.unreachable||(e.unreachTimer=setTimeout(()=>{e.unreachTimer=null,!(this.stopped||this.peers.get(e.id)!==e||e.state==="connected")&&(e.unreachable=!0,this.log("unreachable",{peer:e.id,afterMs:this.unreachableMs,pc:e.pc?e.pc.iceConnectionState:null}),this._setState(e,"unreachable"))},this.unreachableMs))}_setState(e,t){t==="connected"?(clearTimeout(e.unreachTimer),e.unreachTimer=null,e.unreachable=!1):(t==="connecting"||t==="reconnecting")&&(e.unreachable?t="unreachable":this._armUnreachable(e)),e.state!==t&&(e.state=t,this.cb.onPeerState?.(e.id,t))}_signal(e,t){this.session?.send(e.id,{...t,gen:e.gen})}_wireDc(e,t){e.dc=t,t.onopen=()=>this.cb.onMessage?.(e.id,{type:"__open"}),t.onmessage=i=>{let r;try{r=JSON.parse(i.data)}catch{return}if(r&&r.type==="bye")return this._drop(e,"left");this.cb.onMessage?.(e.id,r)}}send(e,t){let i=this.peers.get(e);return i&&i.dc&&i.dc.readyState==="open"?(i.dc.send(JSON.stringify(t)),!0):!1}broadcast(e){for(let t of this.peers.keys())this.send(t,e)}peerConnection(e){let t=this.peers.get(e);return t?t.pc:null}peerState(e){let t=this.peers.get(e);return t?t.state:null}async replaceTrack(e,t,i){i&&(this.localStream=i);for(let r of this.peers.values())if(r.pc)for(let s of r.pc.getTransceivers())(s.receiver&&s.receiver.track?s.receiver.track.kind:null)===e&&await s.sender.replaceTrack(t).catch(()=>{});await this.tuneSenders()}setSendFormat(e){return this.sendFormat=e,this.tuneSenders()}async tuneSenders(){let e=this.peers.size,t=Ve(this.sendFormat,e);for(let i of this.peers.values())if(i.pc){for(let r of i.pc.getSenders())if(!(!r.track||r.track.kind!=="video"))try{let s=r.getParameters();s.degradationPreference="maintain-resolution",(!s.encodings||!s.encodings.length)&&(s.encodings=[{}]),s.encodings[0].maxBitrate=t*1e3,await r.setParameters(s)}catch(s){this.log("setParameters-error",{peer:i.id,err:String(s)})}}return t}stop(){if(!this.stopped){this.broadcast({type:"bye"}),this.stopped=!0;for(let e of this.peers.values())this._clearTimers(e),clearTimeout(e.waitTimer),clearTimeout(e.unreachTimer),this._signal(e,{kind:"bye"}),this._closePc(e);this.peers.clear();try{this.session?.leave()}catch{}}}_debugKill(e){let t=this.peers.get(e);return!t||!t.pc?!1:(this._closePc(t),this._fail(t,"debug-kill"),!0)}};var ji={width:{ideal:1280},height:{ideal:720},frameRate:{ideal:30}},Dt={width:{ideal:3840},height:{ideal:1080},frameRate:{ideal:30}},gr=Object.freeze({echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0});function _r(n){return!!n&&(n.name==="NotReadableError"||n.name==="TrackStartError"||/in use|busy/i.test(n.message||""))}function vr(n){return!!n&&(n.name==="NotAllowedError"||n.name==="PermissionDeniedError"||n.name==="SecurityError")}function Wi(n){return n.length&&n.every(e=>e.busy)?"camera-busy":n.some(e=>e.denied)?"permission-denied":"no-camera"}function Lt(n){return/stereo|\b3d\b|\bsbs\b|dual/i.test(n||"")}async function Ni(n="auto",e={}){let t=e.mediaDevices||globalThis.navigator&&navigator.mediaDevices,i=e.log||(()=>{}),r=[],s=e.calibration||{};if(n&&typeof n=="object"&&typeof n.getVideoTracks=="function"){let m=n.getVideoTracks()[0],u=m?m.getSettings():{},v=e.format==="sbs"?"sbs":"mono";return{stream:n,format:v,width:u.width||0,height:u.height||0,deviceId:u.deviceId||null,label:m?m.label:"",owned:!1,skipped:r,calibration:s}}if(!t||!t.getUserMedia)throw Object.assign(new Error("getUserMedia is not available (insecure context?)"),{code:"no-camera"});let o=async m=>{let u=await t.getUserMedia({video:m,audio:!1}),v=u.getVideoTracks()[0],y=v?v.getSettings():{};if(!v||v.readyState==="ended"||!(y.width>0)||!(y.height>0))throw u.getTracks().forEach(C=>C.stop()),Object.assign(new Error("the camera opened but delivers no picture (0x0)"),{name:"NotReadableError"});let b=y.displayxrStereo&&y.displayxrStereo.layout==="side-by-side"?y.displayxrStereo:null;return{stream:u,track:v,width:y.width,height:y.height,deviceId:y.deviceId||null,label:v.label||"",stereo:b}},a=(m,u)=>{r.push({label:m,error:`${u.name}: ${u.message}`,busy:_r(u),denied:vr(u)}),i("camera-skip",{label:m,error:u.name})},l=m=>m&&m.stream.getTracks().forEach(u=>u.stop()),c=(m,u)=>({stream:m.stream,format:u,width:m.width,height:m.height,deviceId:m.deviceId,label:m.label,owned:!0,skipped:r,calibration:{rectified:!1,...u==="sbs"&&m.stereo?{rectified:!!m.stereo.rectified,...m.stereo.baselineMm>0?{baselineMm:m.stereo.baselineMm}:{},...m.stereo.horizontalFovDeg>0?{hfovDeg:m.stereo.horizontalFovDeg}:{}}:{},...s}});if(typeof n=="string"&&!["auto","stereo","mono"].includes(n)){let m;try{m=await o({deviceId:{exact:n},...Dt})}catch(u){throw a(n,u),Object.assign(new Error(`camera unavailable: ${u.message}`),{code:Wi(r),skipped:r})}return se(m.width,m.height)?c(m,"sbs"):(l(m),c(await o({deviceId:{exact:n},...ji}),"mono"))}let p=new Set;if(n!=="mono"){let m=[];try{m=(await t.enumerateDevices()).filter(u=>u.kind==="videoinput"&&u.deviceId&&Lt(u.label))}catch{}for(let u of m){p.add(u.deviceId);let v=null;try{v=await o({deviceId:{exact:u.deviceId},...Dt})}catch(y){a(u.label,y);continue}if(se(v.width,v.height))return i("camera-sbs",{label:v.label,width:v.width,height:v.height,direct:!0}),c(v,"sbs");l(v)}}let f=null;try{f=await o(ji)}catch(m){a("default",m)}if(n==="mono"&&f)return c(f,"mono");if(f&&se(f.width,f.height))return c(f,"sbs");let h=[];try{h=(await t.enumerateDevices()).filter(m=>m.kind==="videoinput")}catch{}h.sort((m,u)=>Number(Lt(u.label))-Number(Lt(m.label)));for(let m of h){if(!m.deviceId||f&&m.deviceId===f.deviceId||p.has(m.deviceId))continue;let u=null;try{u=await o({deviceId:{exact:m.deviceId},...Dt})}catch(v){a(m.label,v);continue}if(se(u.width,u.height))return l(f),i("camera-sbs",{label:u.label,width:u.width,height:u.height}),c(u,"sbs");l(u)}if(f)return n==="stereo"&&i("camera-no-stereo",{fallback:f.label}),c(f,"mono");let d=Wi(r);throw Object.assign(new Error(d==="camera-busy"?"every camera is in use by another app (e.g. eye tracking)":d==="permission-denied"?"camera access was denied":"no camera could be opened"),{code:d,skipped:r})}async function zi(n={}){let e=n.mediaDevices||globalThis.navigator&&navigator.mediaDevices;try{return(await e.getUserMedia({audio:{...gr},video:!1})).getAudioTracks()[0]||null}catch(t){return(n.log||(()=>{}))("mic-skip",{error:t&&t.name}),null}}function Ue(n,e,t,i,r,s,o,a,l,c,p){if(s<0||s+a>t||o<0)return-1;let f=0,h=0,d=0,m=a*l;for(let y=0;y<l;y++){let b=(r+y)*e+i,C=(o+y)*e+t+s;for(let x=0;x<a;x++){let O=n[C+x];f+=O,h+=O*O,d+=n[b+x]*O}}let u=f/m,v=h/m-u*u;return v<1?-1:(d/m-c*u)/(p*Math.sqrt(v))}function yr(n,e,t,i,r,s){let o=0,a=0;for(let p=0;p<s;p++){let f=(i+p)*e+t;for(let h=0;h<r;h++){let d=n[f+h];o+=d,a+=d*d}}let l=r*s,c=o/l;return{mean:c,std:Math.sqrt(Math.max(0,a/l-c*c))}}function At(n,e,t,i,r,s,o,{dMin:a,dMax:l,dyMax:c=2,uniq:p}={}){let f=e/2,{mean:h,std:d}=yr(n,e,i,r,s,o);if(d<6)return null;let m=-2,u=0,v=0,y=new Map,b=(R,g,w,_,M)=>{for(let A=_;A<=M;A++){let S=r+A;if(!(S<0||S+o>t))for(let F=R;F<=g;F+=w){let z=Ue(n,e,f,i,r,i-F,S,s,o,h,d);z>(y.get(F)??-2)&&y.set(F,z),z>m&&(m=z,u=F,v=A)}}},C=l-a>8;if(b(a,l,C?2:1,-c,c),C&&m>-1){let R=u,g=v;b(Math.max(a,R-2),Math.min(l,R+2),1,Math.max(-c,g-1),Math.min(c,g+1))}if(m<-1)return null;let x=-2,O=R=>{let g=-2;for(let w=-c;w<=c;w++){let _=r+w;if(!(_<0||_+o>t))for(let M=R-1;M<=R+1;M++)g=Math.max(g,Ue(n,e,f,i,r,i-M,_,s,o,h,d))}return g};for(let[R,g]of y){if(Math.abs(R-u)<3||g<=x)continue;let _=g>=(y.get(R-2)??-2)&&g>=(y.get(R+2)??-2)&&g>0?O(R):g;_>x&&(x=_)}if(l-a>12&&x>-2&&m-x<(p??.08))return null;let T=Ue(n,e,f,i,r,i-(u-1),r+v,s,o,h,d),I=Ue(n,e,f,i,r,i-(u+1),r+v,s,o,h,d),P=0,L=T-2*m+I;return T>-1&&I>-1&&L<0&&(P=Math.max(-.5,Math.min(.5,.5*(T-I)/L))),{d:u+P,dy:v,c:m}}function wr(n,e,t,i={}){let r=e/2,s=i.block||Math.max(8,Math.round(r/20)),o=i.step||Math.round(s*1.5),a=i.dMax??Math.round(r*.3),l=i.dMin??-Math.round(r*.05),c=Math.round(r*(i.roiX0??.15)),p=Math.round(r*(i.roiX1??.85))-s,f=Math.round(t*(i.roiY0??.05)),h=Math.round(t*(i.roiY1??.85))-s,d=[];for(let m=f;m<=h;m+=o)for(let u=c;u<=p;u+=o){let v=At(n,e,t,u,m,s,s,{dMin:l,dMax:a,dyMax:i.dyMax??2,uniq:i.uniq});v&&v.c>=(i.minNcc??.8)&&d.push({x:u,y:m,...v})}return d}function br(n,{tol:e=2,minFrac:t=.12,minBlocks:i=3}={}){if(!n.length)return null;let r=Math.max(i,Math.ceil(n.length*t)),s=n.map(o=>o.d).sort((o,a)=>a-o);for(let o of s){let a=n.filter(l=>Math.abs(l.d-o)<=e);if(a.length>=r){let l=a.map(c=>c.d).sort((c,p)=>c-p);return{d:l[l.length>>1],members:a}}}return null}function xr(n,e){let t=Math.min(...n.map(l=>l.y)),r=n.filter(l=>l.y<=t+2*e).map(l=>l.x),s=Math.min(...r),o=Math.max(...r)+e,a=o-s;return{x:(s+o)/2,y:t+.4*1.3*a}}function It(n,e,t,i={}){let r=e/2,s=i.block||Math.max(8,Math.round(r/20)),o=i.dMax??Math.round(r*.3),a=i.dMin??-Math.round(r*.05),l=i.focus||null,c="focus",p=0,f=null;if(!l){let C=wr(n,e,t,{...i,block:s,dMax:o,dMin:a});p=C.length;let x=br(C,i);if(!x)return null;l=xr(x.members,s),f=x.d,c="mode"}let h=Math.round(s*(i.refineW??3)),d=Math.round(s*(i.refineH??1.5)),m=Math.round(Math.max(0,Math.min(r-h,l.x-h/2))),u=Math.round(Math.max(0,Math.min(t-d,l.y-d/2))),v=f===null?a:Math.max(a,Math.floor(f)-4),y=f===null?o:Math.min(o,Math.ceil(f)+4),b=At(n,e,t,m,u,h,d,{dMin:v,dMax:y,dyMax:i.dyMax??2});return b&&b.c>=(i.minNcc??.8)?{d:b.d,x:l.x,y:l.y,c:b.c,method:c,blocks:p}:f!==null?{d:f,x:l.x,y:l.y,c:0,method:c,blocks:p}:null}function Be(n,e){let t=new Uint8Array(e);for(let i=0,r=0;i<e;i++,r+=4)t[i]=n[r]*77+n[r+1]*150+n[r+2]*29>>8;return t}function qe({n=3}={}){let e=[],t={value:null,push(i){if(i===null||!Number.isFinite(i))return t.value;e.push(i),e.length>n&&e.shift();let r=[...e].sort((s,o)=>s-o);return t.value=r[r.length>>1],t.value},reset(){e.length=0,t.value=null}};return t}function Hi(n,e,t,i,r,s){let o=new Float32Array(r*s);for(let a=0;a<s;a++)for(let l=0;l<r;l++)o[a*r+l]=n[(i+a)*e+t+l];return o}function Sr(n,e,t,i,r,s,o,a,l,c){let p=e/2,f=r*s,h=0,d=0;for(let b=0;b<f;b++)h+=i[b],d+=i[b]*i[b];h/=f;let m=Math.sqrt(Math.max(1e-6,d/f-h*h)),u=-2,v=o,y=a;for(let b=Math.max(0,a-c);b<=Math.min(t-s,a+c);b++)for(let C=Math.max(0,o-l);C<=Math.min(p-r,o+l);C++){let x=0,O=0,T=0;for(let R=0;R<s;R++){let g=(b+R)*e+C;for(let w=0;w<r;w++){let _=n[g+w];x+=_,O+=_*_,T+=_*i[R*r+w]}}let I=x/f,P=O/f-I*I;if(P<1)continue;let L=(T/f-I*h)/(Math.sqrt(P)*m);L>u&&(u=L,v=C,y=b)}return{x:v,y,c:u}}function Ce({fullEveryMs:n=2e3,dWin:e=4,rx:t=12,ry:i=8,minTrackNcc:r=.75,jump:s=8}={}){let o=null,a=null;return{measure(c,p,f,h,d={}){let m=p/2,u=d.block||Math.max(8,Math.round(m/20)),v=Math.round(u*3),y=Math.round(u*1.5),b=null;if(o&&o.w===v&&o.h===y){let I=Sr(c,p,f,o.tpl,v,y,o.x,o.y,t,i);if(I.c>=r){let P=At(c,p,f,I.x,I.y,v,y,{dMin:Math.floor(o.d)-e,dMax:Math.ceil(o.d)+e,dyMax:2});P&&P.c>=.8&&(b={m:P,f:I})}}let C=({m:I,f:P})=>(o={...o,x:P.x,y:P.y,d:I.d,tpl:Hi(c,p,P.x,P.y,v,y)},{d:I.d,x:P.x+v/2,y:P.y+y/2,c:I.c,method:"track",blocks:0});if(b&&h-o.at<n)return C(b);let x=It(c,p,f,d);if(b&&(!x||Math.abs(x.d-b.m.d)>s)){let I=x&&a&&Math.abs(a.d-x.d)<=3;if(a=x&&!I?{d:x.d}:null,!I)return o.at=h,C(b)}else a=null;if(!x)return o=null,null;let O=Math.round(Math.max(0,Math.min(m-v,x.x-v/2))),T=Math.round(Math.max(0,Math.min(f-y,x.y-y/2)));return o={x:O,y:T,d:x.d,tpl:Hi(c,p,O,T,v,y),w:v,h:y,at:h},x},reset(){o=null,a=null}}}function Vi(n,e,t,i,r,s){let o=Math.max(1,s|0),a=Math.floor(i/o);a-=a&1;let l=Math.floor(r/o),c=new Uint8Array(a*l);if(o<=2){let h=o*o;for(let d=0;d<l;d++)for(let m=0;m<a;m++){let u=0;for(let v=0;v<o;v++){let y=e+(d*o+v)*t+m*o;for(let b=0;b<o;b++)u+=n[y+b]}c[d*a+m]=u/h|0}return{img:c,w:a,h:l}}let p=o>>2,f=3*o>>2;for(let h=0;h<l;h++){let d=e+(h*o+p)*t,m=e+(h*o+f)*t;for(let u=0;u<a;u++){let v=u*o+p,y=u*o+f;c[h*a+u]=n[d+v]+n[d+y]+n[m+v]+n[m+y]>>2}}return{img:c,w:a,h:l}}var $i="http://displayxr.org/ns/stereo/1.0/",Xe="http://ns.adobe.com/xap/1.0/\0";function Je(n={}){let e=i=>typeof i=="number"&&Number.isFinite(i)?i:null,t=n.layout==="sbs"||n.layout==="side-by-side"?"sbs":"mono";return{layout:t,columns:t==="sbs"?2:1,rows:1,convergencePx:e(n.convergencePx),baselineMm:e(n.baselineMm),horizontalFovDeg:e(n.horizontalFovDeg),rectified:n.rectified===!0?!0:n.rectified===!1?!1:null,eyeWidth:e(n.eyeWidth),eyeHeight:e(n.eyeHeight),software:typeof n.software=="string"&&n.software?n.software:null}}var Mr=n=>String(n).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<"),de=n=>Math.round(n*1e3)/1e3;function Ui(n){let e=Je(n),t=[["Layout",e.layout==="sbs"?"side-by-side":"mono"],["Columns",e.columns],["Rows",e.rows],["ConvergencePx",e.convergencePx===null?null:de(e.convergencePx)],["BaselineMm",e.baselineMm===null?null:de(e.baselineMm)],["HorizontalFovDeg",e.horizontalFovDeg===null?null:de(e.horizontalFovDeg)],["Rectified",e.rectified===null?null:e.rectified?"True":"False"],["EyeWidth",e.eyeWidth],["EyeHeight",e.eyeHeight],["Software",e.software]].filter(([,i])=>i!=null).map(([i,r])=>` dxr:${i}="${Mr(r)}"`).join("");return`<?xpacket begin="\uFEFF" id="W5M0MpCehiHzreSzNTczkc9d"?><x:xmpmeta xmlns:x="adobe:ns:meta/"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:dxr="${$i}"${t}/></rdf:RDF></x:xmpmeta><?xpacket end="w"?>`}function Pt(n){if(typeof n!="string"||!n.includes($i))return null;let e=o=>{let a=new RegExp(`\\bdxr:${o}="([^"]*)"`).exec(n);if(a)return a[1];let l=new RegExp(`<dxr:${o}>([^<]*)</dxr:${o}>`).exec(n);return l?l[1]:null},t=o=>{let a=e(o);return a===null||a===""||!Number.isFinite(+a)?null:+a},i=e("Rectified"),r=e("Layout"),s=e("Software");return Je({layout:r==="side-by-side"||r==="sbs"?"sbs":"mono",convergencePx:t("ConvergencePx"),baselineMm:t("BaselineMm"),horizontalFovDeg:t("HorizontalFovDeg"),rectified:i===null?null:/^true$/i.test(i),eyeWidth:t("EyeWidth"),eyeHeight:t("EyeHeight"),software:s===null?null:s.replace(/"/g,'"').replace(/</g,"<").replace(/&/g,"&")})}var Ge=n=>new TextEncoder().encode(n),Ot=n=>new TextDecoder().decode(n),Bi=n=>n.length>4&&n[0]===255&&n[1]===216;function*qi(n){let e=2;for(;e+4<=n.length;){if(n[e]!==255)return;let t=n[e+1];if(t===216||t>=208&&t<=215||t===1||t===255){e+=t===255?1:2;continue}if(t===218||t===217)return;let i=n[e+2]<<8|n[e+3];if(i<2||e+2+i>n.length)return;yield{marker:t,start:e,end:e+2+i,data:n.subarray(e+4,e+2+i)},e+=2+i}}function Xi(n,e){if(n.length<e.length)return!1;for(let t=0;t<e.length;t++)if(n[t]!==e.charCodeAt(t))return!1;return!0}function Gi(n,e){if(!Bi(n))throw new TypeError("jpegWithXmp: not a JPEG");let t=new Uint8Array([...Ge(Xe),...Ge(e)]),i=t.length+2;if(i>65535)throw new RangeError("jpegWithXmp: XMP packet too large for one APP1 segment");let r=new Uint8Array(4+t.length);r[0]=255,r[1]=225,r[2]=i>>8,r[3]=i&255,r.set(t,4);let s=2,o=null;for(let p of qi(n)){if(p.marker===225&&Xi(p.data,Xe)){o=p;break}if(p.marker===224||p.marker===225)s=p.end;else break}let[a,l]=o?[o.start,o.end]:[s,s],c=new Uint8Array(n.length-(l-a)+r.length);return c.set(n.subarray(0,a),0),c.set(r,a),c.set(n.subarray(l),a+r.length),c}function Ft(n){if(!Bi(n))return null;for(let e of qi(n))if(e.marker===225&&Xi(e.data,Xe))return Ot(e.data.subarray(Xe.length));return null}var Ji=n=>Pt(Ft(n)),H={EBML:440786851,Segment:408125543,Tags:307544935,Tag:29555,Targets:25536,SimpleTag:26568,TagName:17827,TagString:17543},Er=n=>n.length>4&&n[0]===26&&n[1]===69&&n[2]===223&&n[3]===163;function Ki(n){let e=[];for(let t=n;t>0;t=Math.floor(t/256))e.unshift(t%256);return e}function Yi(n,e=0){let t=e;if(!t)for(t=1;t<8&&n>2**(7*t)-2;t++);let i=new Array(t).fill(0),r=n;for(let s=t-1;s>=1;s--)i[s]=r%256,r=Math.floor(r/256);return i[0]=128>>t-1|r,i}function jt(n,e){let t=n[e],i=t>=128?1:t>=64?2:t>=32?3:t>=16?4:0;if(!i||e+i>n.length)return null;let r=0;for(let s=0;s<i;s++)r=r*256+n[e+s];return{id:r,width:i}}function Re(n,e){let t=n[e],i=1;for(;i<=8&&!(t&128>>i-1);)i++;if(i>8||e+i>n.length)return null;let r=t&255>>i,s=r===127>>i-1;for(let o=1;o<i;o++)r=r*256+n[e+o],n[e+o]!==255&&(s=!1);return{size:r,width:i,unknown:s}}function ce(n,e){return[...Ki(n),...Yi(e.length),...e]}function kr(n){let e=[];for(let[i,r]of Object.entries(n))r!=null&&e.push(...ce(H.SimpleTag,[...ce(H.TagName,[...Ge(String(i))]),...ce(H.TagString,[...Ge(String(r))])]));let t=ce(H.Tag,[...ce(H.Targets,[]),...e]);return new Uint8Array(ce(H.Tags,t))}function Zi(n){let e=Je(n);return{DXR_LAYOUT:e.layout==="sbs"?"side-by-side":"mono",DXR_COLUMNS:String(e.columns),DXR_ROWS:String(e.rows),DXR_CONVERGENCE_PX:e.convergencePx===null?null:String(de(e.convergencePx)),DXR_BASELINE_MM:e.baselineMm===null?null:String(de(e.baselineMm)),DXR_HFOV_DEG:e.horizontalFovDeg===null?null:String(de(e.horizontalFovDeg)),DXR_RECTIFIED:e.rectified===null?null:e.rectified?"true":"false",DXR_EYE_WIDTH:e.eyeWidth===null?null:String(e.eyeWidth),DXR_EYE_HEIGHT:e.eyeHeight===null?null:String(e.eyeHeight),DXR_SOFTWARE:e.software}}function Tr(n){if(!n||!("DXR_LAYOUT"in n))return null;let e=t=>n[t]===void 0||n[t]===""||!Number.isFinite(+n[t])?null:+n[t];return Je({layout:n.DXR_LAYOUT==="side-by-side"?"sbs":"mono",convergencePx:e("DXR_CONVERGENCE_PX"),baselineMm:e("DXR_BASELINE_MM"),horizontalFovDeg:e("DXR_HFOV_DEG"),rectified:n.DXR_RECTIFIED===void 0?null:n.DXR_RECTIFIED==="true",eyeWidth:e("DXR_EYE_WIDTH"),eyeHeight:e("DXR_EYE_HEIGHT"),software:n.DXR_SOFTWARE??null})}function Qi(n){if(!Er(n))return null;let e=Re(n,4);if(!e)return null;let t=4+e.width+e.size;for(;t<n.length;){let i=jt(n,t);if(!i)return null;let r=Re(n,t+i.width);if(!r)return null;let s=t+i.width+r.width;if(i.id===H.Segment)return{sizeAt:t+i.width,sizeWidth:r.width,unknown:r.unknown,dataStart:s,size:r.size};if(r.unknown)return null;t=s+r.size}return null}function en(n,e){let t=Qi(n);if(!t)throw new TypeError("webmWithTags: not a WebM/Matroska file (no Segment)");let i=kr(e);if(t.unknown){let p=new Uint8Array(n.length+i.length);return p.set(n,0),p.set(i,n.length),p}let r=Math.min(n.length,t.dataStart+t.size),s=r-t.dataStart+i.length,o=s<=2**(7*t.sizeWidth)-2,a=Yi(s,o?t.sizeWidth:8),l=new Uint8Array(t.sizeAt+a.length+(r-t.dataStart)+i.length+(n.length-r));l.set(n.subarray(0,t.sizeAt),0),l.set(a,t.sizeAt);let c=t.sizeAt+a.length;return l.set(n.subarray(t.dataStart,r),c),c+=r-t.dataStart,l.set(i,c),c+=i.length,l.set(n.subarray(r),c),l}function tn(n,e,t){let i={},r=(s,o,a)=>{let l=s;for(;l<o;){let c=jt(n,l);if(!c)return;let p=Re(n,l+c.width);if(!p||p.unknown)return;let f=l+c.width+p.width;a(c.id,f,Math.min(o,f+p.size)),l=f+p.size}};return r(e,t,(s,o,a)=>{s===H.Tag&&r(o,a,(l,c,p)=>{if(l!==H.SimpleTag)return;let f=null,h=null;r(c,p,(d,m,u)=>{d===H.TagName?f=Ot(n.subarray(m,u)):d===H.TagString&&(h=Ot(n.subarray(m,u)))}),f!==null&&(i[f]=h??"")})}),i}function Cr(n){let e=Qi(n);if(!e)return null;let t=e.unknown?n.length:Math.min(n.length,e.dataStart+e.size),i=null,r=e.dataStart;for(;r<t;){let s=jt(n,r);if(!s)break;let o=Re(n,r+s.width);if(!o)break;let a=r+s.width+o.width;if(s.id===H.Tags&&!o.unknown&&(i={...i||{},...tn(n,a,Math.min(t,a+o.size))}),o.unknown){i=i||Rr(n,t);break}r=a+o.size}return i}function Rr(n,e){let t=Ki(H.Tags);for(let i=e-t.length-1;i>=0;i--){if(n[i]!==t[0]||n[i+1]!==t[1]||n[i+2]!==t[2]||n[i+3]!==t[3])continue;let r=Re(n,i+4);if(r&&!r.unknown&&i+4+r.width+r.size===e)return tn(n,i+4+r.width,e)}return null}var nn=n=>Tr(Cr(n));var he="[inline3d/camera]",on="inline3d-camera/1",Dr=200,Lr=240,Ar=4e3,Ir=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm","video/mp4"],Ke=()=>typeof document<"u"&&document&&typeof document.createElement=="function",rn=()=>{let n=new Date,e=t=>String(t).padStart(2,"0");return`${n.getFullYear()}${e(n.getMonth()+1)}${e(n.getDate())}-${e(n.getHours())}${e(n.getMinutes())}${e(n.getSeconds())}`},Or=n=>/jpe?g/.test(n)?"jpg":/png/.test(n)?"png":/webp/.test(n)?"webp":/mp4/.test(n)?"mp4":/webm/.test(n)?"webm":"bin";function Ye(n,e,t){return`${String(n||"capture").replace(/[^\w.-]+/g,"-").replace(/^-+|-+$/g,"")||"capture"}${e==="sbs"?"_2x1":""}.${Or(t)}`}var K=(n,e,t={})=>Object.assign(new Error(`${he} ${n}`),{code:e,...t});function sn(n,e=Ar){return n?(n.readyState||0)>=2&&n.videoWidth?Promise.resolve():new Promise((t,i)=>{let r=!1,s=()=>{r||(n.readyState||0)<2||!n.videoWidth||(r=!0,clearTimeout(o),n.removeEventListener("loadeddata",s),n.removeEventListener("playing",s),n.removeEventListener("resize",s),t())},o=setTimeout(()=>{r||(r=!0,i(K("the camera delivered no frame in time","no-frame")))},e);n.addEventListener("loadeddata",s),n.addEventListener("playing",s),n.addEventListener("resize",s),n.play?.().catch(()=>{})}):Promise.reject(K("no video element (no document?)","no-frame"))}function an(n,e,t=Lr){let i=n.videoWidth,r=n.videoHeight;if(!i||!r||(n.readyState||0)<2)return null;let s=Math.min(1,t/(i/2)),o=Math.max(2,Math.round(i*s/2)*2),a=Math.max(2,Math.round(r*s));(e.width!==o||e.height!==a)&&(e.width=o,e.height=a);let l=e.getContext("2d",{willReadFrequently:!0});try{return l.drawImage(n,0,0,o,a),{img:Be(l.getImageData(0,0,o,a).data,o*a),w:o,h:a,scale:o/i}}catch{return null}}var Wt=class{constructor(e,{log:t=null}={}){this.format=e.format,this.stream=e.stream,this.width=e.width||0,this.height=e.height||0,this.deviceId=e.deviceId||null,this.label=e.label||"",this.owned=!!e.owned,this.skipped=Object.freeze([...e.skipped||[]]),this.calibration=Object.freeze({...e.calibration||{}});let i=this.calibration;this.stereo=this.format==="sbs"?Object.freeze({rectified:!!i.rectified,baselineMm:i.baselineMm>0?i.baselineMm:null,horizontalFovDeg:i.hfovDeg>0?i.hfovDeg:null}):null,this.state="live",this._log=t,this._listeners=new Map,this._scratch=null,this._views=new Set,this.video=null,Ke()&&(this.video=Object.assign(document.createElement("video"),{muted:!0,playsInline:!0,autoplay:!0}),this.video.srcObject=this.stream,this.video.play?.().catch(()=>{})),this._onEnded=()=>this._ended("ended");for(let r of this.stream.getVideoTracks())r.addEventListener?.("ended",this._onEnded)}get eyeWidth(){return this.format==="sbs"?this.width/2:this.width}log(e,t={}){this._log&&this._log(e,t)}on(e,t){if(typeof t!="function")throw new TypeError(`${he} on() takes a function`);return this._listeners.has(e)||this._listeners.set(e,new Set),this._listeners.get(e).add(t),()=>this._listeners.get(e)?.delete(t)}off(e,t){this._listeners.get(e)?.delete(t)}_emit(e,t){for(let i of[...this._listeners.get(e)||[]])try{i(t)}catch(r){console.error(`${he} '${e}' listener threw`,r)}}_ended(e){this.state==="live"&&(this.state="ended",this.log("ended",{reason:e}),this._emit("ended",{reason:e}))}async measureConvergence(){if(this.format!=="sbs"||!this.video||!Ke())return null;try{await sn(this.video)}catch{return null}this._scratch=this._scratch||document.createElement("canvas");let e=an(this.video,this._scratch);if(!e)return null;let t=Ce().measure(e.img,e.w,e.h,0);return t?t.d/e.scale:null}_meta(e,t=this.width,i=this.height){let r=this.stereo;return{layout:this.format,convergencePx:e,baselineMm:r?r.baselineMm:null,horizontalFovDeg:r?r.horizontalFovDeg:null,rectified:r?r.rectified:null,eyeWidth:this.format==="sbs"?t/2:t,eyeHeight:i,software:on}}async capturePhoto({type:e="image/jpeg",quality:t=.92,name:i,convergencePx:r}={}){if(this.state==="closed")throw K("the camera is closed","closed");if(!this.video||!Ke())throw K("capturePhoto needs a document","no-frame");await sn(this.video);let s=this.video.videoWidth,o=this.video.videoHeight,a=typeof r=="number"&&Number.isFinite(r)?r:await this.measureConvergence(),l=document.createElement("canvas");l.width=s,l.height=o,l.getContext("2d").drawImage(this.video,0,0,s,o);let c=await new Promise((d,m)=>l.toBlob(u=>u?d(u):m(K("toBlob produced nothing","encode-failed")),e,t)),p=this._meta(a,s,o),f=null;(c.type==="image/jpeg"||/jpe?g/.test(e))&&(f=Ui(p),c=new Blob([Gi(new Uint8Array(await c.arrayBuffer()),f)],{type:"image/jpeg"}));let h={blob:c,type:c.type||e,width:s,height:o,layout:this.format,convergencePx:a,stereo:this.stereo,suggestedName:Ye(i||`photo-${rn()}`,this.format,c.type||e),xmp:f};return this.log("photo",{width:s,height:o,layout:this.format,convergencePx:a,bytes:c.size,name:h.suggestedName}),h}record({mimeType:e,mono:t=!1,audio:i=null,videoBitsPerSecond:r,timesliceMs:s=1e3,name:o,fps:a=30}={}){if(this.state==="closed")throw K("the camera is closed","closed");if(typeof MediaRecorder!="function")throw K("MediaRecorder is not available here","unsupported");let l=e||Ir.find(g=>typeof MediaRecorder.isTypeSupported!="function"||MediaRecorder.isTypeSupported(g))||"";if(l&&typeof MediaRecorder.isTypeSupported=="function"&&!MediaRecorder.isTypeSupported(l))throw K(`${l} is not a supported recording type here`,"unsupported");let c=[...this.stream.getVideoTracks()],p=i&&typeof i.getAudioTracks=="function"?i.getAudioTracks():i&&i.kind==="audio"?[i]:[];c.push(...p);let f=new MediaStream(c),h={...l?{mimeType:l}:{},...r?{videoBitsPerSecond:r}:{}},d=new MediaRecorder(f,h),m=[];d.ondataavailable=g=>g.data&&g.data.size&&m.push(g.data);let u=null,v=[],y=null,b=0,C=!!t&&this.format==="sbs"&&Ke()&&this.video;if(C){y=document.createElement("canvas");let g=()=>{b=requestAnimationFrame(g);let _=this.video,M=_.videoWidth,A=_.videoHeight;!M||!A||(_.readyState||0)<2||((y.width!==M/2||y.height!==A)&&(y.width=M/2,y.height=A),y.getContext("2d").drawImage(_,0,0,M/2,A,0,0,M/2,A))};g();let w=y.captureStream(a);for(let _ of p)w.addTrack(_);u=new MediaRecorder(w,h),u.ondataavailable=_=>_.data&&_.data.size&&v.push(_.data)}let x=performance.now(),O=[],T=this.format==="sbs"?setInterval(()=>this.measureConvergence().then(g=>g!==null&&O.push(g)),1500):0;this.measureConvergence().then(g=>g!==null&&O.push(g)),d.start(s),u?.start(s),this.log("record-start",{mimeType:l,mono:C,audio:p.length});let I=(g,w)=>new Promise(_=>{if(!g||g.state==="inactive")return _(w);g.onstop=()=>_(w),g.stop()}),P=o||`clip-${rn()}`,L=this;return{get state(){return d.state},get mimeType(){return d.mimeType||l},pause(){d.state==="recording"&&d.pause(),u&&u.state==="recording"&&u.pause()},resume(){d.state==="paused"&&d.resume(),u&&u.state==="paused"&&u.resume()},async stop(){clearInterval(T),b&&cancelAnimationFrame(b);let[g,w]=await Promise.all([I(d,m),I(u,v)]),_=d.mimeType||l||g[0]&&g[0].type||"video/webm",M=[...O].sort((me,$)=>me-$),A=M.length?M[Math.floor(M.length/2)]:null,S=L._meta(A),F=/webm|matroska/.test(_),z=async(me,$)=>{let Z=new Blob(me,{type:_});if(F&&Z.size)try{Z=new Blob([en(new Uint8Array(await Z.arrayBuffer()),Zi({...S,layout:$}))],{type:_})}catch(ti){L.log("record-tag-failed",{message:String(ti&&ti.message)})}return Z},k=await z(g,L.format),j={blob:k,type:_,layout:L.format,durationMs:Math.round(performance.now()-x),convergencePx:A,stereo:L.stereo,suggestedName:Ye(P,L.format,_),tagged:F&&k.size>0};return u&&(j.mono=await z(w,"mono"),j.monoSuggestedName=Ye(P,"mono",_)),L.log("record-stop",{bytes:k.size,mono:j.mono?j.mono.size:null,ms:j.durationMs,convergencePx:A,name:j.suggestedName}),j}}}close(){if(this.state!=="closed"){this.state="closed";for(let e of this.stream.getVideoTracks())e.removeEventListener?.("ended",this._onEnded);for(let e of[...this._views])e.remove();this.owned&&this.stream.getTracks().forEach(e=>e.stop()),this.video&&(this.video.srcObject=null),this.log("closed",{})}}};async function zt(n={}){let e=typeof n=="string"||n&&typeof n.getVideoTracks=="function"?{prefer:n}:n||{},t=e.prefer===void 0||e.prefer===null?"auto":e.prefer,i=typeof e.log=="function"?e.log:e.debug?(a,l)=>console.log(`${he} ${a} ${JSON.stringify(l)}`):null,r=e.calibration&&typeof e.calibration=="object"?{...e.calibration}:{};r.horizontalFovDeg>0&&!(r.hfovDeg>0)&&(r.hfovDeg=r.horizontalFovDeg),delete r.horizontalFovDeg;let s=await Ni(t,{format:e.format,calibration:r,mediaDevices:e.mediaDevices,log:i||void 0});if(s.format==="sbs"&&typeof e.rectify=="function")try{let a=await e.rectify(s.stream,{width:s.width,height:s.height,deviceId:s.deviceId,label:s.label});a&&typeof a.getVideoTracks=="function"&&(s.stream=a,s.calibration={...s.calibration,rectified:!0})}catch(a){i?.("rectify-failed",{message:String(a&&a.message)}),s.rectifyError=a}let o=new Wt(s,{log:i});return s.rectifyError&&(o.rectifyError=s.rectifyError),o.log("open",{format:o.format,width:o.width,height:o.height,label:o.label,stereo:o.stereo,skipped:o.skipped.length}),o}var Ze=n=>!!n&&typeof n=="object"&&typeof n.capturePhoto=="function"&&typeof n.record=="function"&&n.stream&&typeof n.stream.getVideoTracks=="function";function Pr(n){let e=Math.min(globalThis.devicePixelRatio||1,2),t=Math.round((n.clientWidth||0)*e),i=Math.round((n.clientHeight||0)*e);return!t||!i?!1:((n.width!==t||n.height!==i)&&(n.width=t,n.height=i),!0)}function Ht(n,e,t,i={}){if(!e||typeof e.getContext!="function")throw new TypeError(`${he} addCameraView(wall, canvas, cam, opts) needs a canvas`);if(!Ze(t))throw new TypeError(`${he} addCameraView: cam must be a StereoCamera from openCamera()`);let r=new Nt(n,e,t,i);return t._views?.add(r),r}var Nt=class{constructor(e,t,i,r){this.wall=e||null,this.canvas=t,this.cam=i,this.mirror=r.mirror===void 0?!0:!!r.mirror,this.aspect=typeof r.aspect=="number"&&r.aspect>.3&&r.aspect<4?r.aspect:16/9,this.autoConverge=!!r.autoConverge,this.conv=xe(),this.conv.depth=0,this.setDepth(r.depth),this.route=null,this.handle=null,this.buffer=null,this.removed=!1,this._raf=0,this._loop=r._loop!==!1,this._autoAt=0,this._track=qe(),this._focus=Ce(),this._scratch=null,this.disparityPx=null,this._reroute(!1),this._loop&&this._start()}get woven(){return this.route==="woven-sbs"}get convergencePx(){return this.conv.current}get depth(){return this.conv.depth}setDepth(e){let t=e==null||!Number.isFinite(+e)?0:Math.max(-1,Math.min(1,+e));return this.conv.depth=t,t}setMirror(e){return this.mirror=e===void 0?!this.mirror:!!e,this.mirror}setAutoConverge(e){return this.autoConverge=e===void 0?!this.autoConverge:!!e,this.autoConverge||(this._track.reset(),this._focus.reset(),this.conv.measuredPx=null,this.disparityPx=null),this.autoConverge}_reroute(e,t){if(t!==void 0&&(this.wall=t),this.removed)return;let i=this.cam,r=i.state==="live"&&i.video,s=i.format==="sbs"&&r&&this.wall&&this.wall.supported?"woven-sbs":i.format==="sbs"?"flat-left":"flat";!e&&s===this.route||(this._unregister(),this.route=s,s==="woven-sbs"&&(this.buffer||(this.buffer=document.createElement("canvas")),this._paintWoven(),this.handle=this.wall.addImage(this.canvas,this.buffer)))}_onWallLost(){this._reroute(!0,{supported:!1})}_unregister(){if(this.handle){try{this.handle.remove()}catch{}this.handle=null}}_start(){let e=()=>{this._raf=requestAnimationFrame(e),this.paint()};this._raf=requestAnimationFrame(e)}paint(){if(this.removed)return;let e=this.cam.video;!e||this.cam.state==="closed"||(this.route==="woven-sbs"?this._paintWoven():this._paintFlat(e))}_paintFlat(e){if(!Pr(this.canvas))return;let t=e.videoWidth,i=e.videoHeight;if(!t||!i||(e.readyState||0)<2)return;let r=this.canvas.getContext("2d"),s=this.route==="flat-left"?t/2:t,o=X(s,i,this.canvas.width/this.canvas.height,0,0);r.save(),this.mirror&&(r.translate(this.canvas.width,0),r.scale(-1,1)),r.drawImage(e,o.sx,o.sy,o.sw,o.sh,0,0,this.canvas.width,this.canvas.height),r.restore()}_paintWoven(){let e=this.cam.video,t=e.videoWidth,i=e.videoHeight;if(!t||!i||(e.readyState||0)<2||!this.buffer)return;let r=t/2,s=this.aspect,{w:o,h:a}=be(r,i,s),l=this.buffer;(l.width!==2*o||l.height!==a)&&(l.width=2*o,l.height=a),this.autoConverge&&this._sample(e);let c=this.conv.step(r),p=l.getContext("2d");if(this.mirror)for(let f of oe(t,i)){let h=f.src==="L"?0:1,d=X(r,i,s,c,h),m=f.dx===0?0:o;p.save(),p.translate(m+o,0),p.scale(-1,1),p.drawImage(e,f.sx+d.sx,d.sy,d.sw,d.sh,0,0,o,a),p.restore()}else for(let f of[0,1]){let h=X(r,i,s,c,f);p.drawImage(e,f*r+h.sx,h.sy,h.sw,h.sh,f*o,0,o,a)}}_sample(e){let t=performance.now();if(t-this._autoAt<Dr)return;this._autoAt=t,this._scratch=this._scratch||document.createElement("canvas");let i=an(e,this._scratch),r=i?this._focus.measure(i.img,i.w,i.h,t):null,s=this._track.push(r?r.d/i.scale:null);this.conv.measuredPx=s,this.disparityPx=s}remove(){this.removed||(this.removed=!0,this._raf&&cancelAnimationFrame(this._raf),this._raf=0,this._unregister(),this.cam._views?.delete(this))}};var cn=[[-1,7,10,15,20,26,18,20,24,30,18],[-1,10,16,26,18,24,16,18,22,22,26]],dn=[[-1,1,1,1,1,1,2,2,2,2,4],[-1,1,1,1,2,2,4,4,4,5,5]],Fr=[1,0],Vt=10;function hn(n){let e=(16*n+128)*n+64;if(n>=2){let t=Math.floor(n/7)+2;e-=(25*t-10)*t-55,n>=7&&(e-=36)}return e}var ln=(n,e)=>Math.floor(hn(n)/8)-cn[e][n]*dn[e][n];function $t(n,e){let t=0;for(let i=7;i>=0;i--)t=t<<1^(t>>>7)*285,t^=(e>>>i&1)*n;return t}function jr(n){let e=new Array(n-1).fill(0);e.push(1);let t=1;for(let i=0;i<n;i++){for(let r=0;r<e.length;r++)e[r]=$t(e[r],t),r+1<e.length&&(e[r]^=e[r+1]);t=$t(t,2)}return e}function Wr(n,e){let t=e.map(()=>0);for(let i of n){let r=i^t.shift();t.push(0),e.forEach((s,o)=>t[o]^=$t(s,r))}return t}function Ut(n,e={}){let t=e.ecl==="L"?0:1,i=[...new TextEncoder().encode(String(n))],r=1;for(;r<=Vt&&!(4+(r<=9?8:16)+i.length*8<=ln(r,t)*8);r++);if(r>Vt)throw new Error(`qrEncode: ${i.length} bytes is too long for a version-${Vt} code`);let s=[],o=(g,w)=>{for(let _=w-1;_>=0;_--)s.push(g>>>_&1)};o(4,4),o(i.length,r<=9?8:16);for(let g of i)o(g,8);let a=ln(r,t)*8;o(0,Math.min(4,a-s.length)),o(0,(8-s.length%8)%8);for(let g=236;s.length<a;g^=253)o(g,8);let l=[];for(let g=0;g<s.length;g+=8)l.push(s.slice(g,g+8).reduce((w,_)=>w<<1|_,0));let c=dn[t][r],p=cn[t][r],f=Math.floor(hn(r)/8),h=c-f%c,d=Math.floor(f/c),m=jr(p),u=[];for(let g=0,w=0;g<c;g++){let _=l.slice(w,w+d-p+(g<h?0:1));w+=_.length;let M=Wr(_,m);g<h&&_.push(0),u.push(_.concat(M))}let v=[];for(let g=0;g<u[0].length;g++)for(let w=0;w<u.length;w++)(g!==d-p||w>=h)&&v.push(u[w][g]);let y=r*4+17,b=Array.from({length:y},()=>new Array(y).fill(!1)),C=Array.from({length:y},()=>new Array(y).fill(!1)),x=(g,w,_)=>{b[w][g]=_,C[w][g]=!0};for(let g=0;g<y;g++)x(6,g,g%2===0),x(g,6,g%2===0);let O=(g,w)=>{for(let _=-4;_<=4;_++)for(let M=-4;M<=4;M++){let A=Math.max(Math.abs(M),Math.abs(_)),S=g+M,F=w+_;S>=0&&S<y&&F>=0&&F<y&&x(S,F,A!==2&&A!==4)}};O(3,3),O(y-4,3),O(3,y-4);let T=[];if(r>1){let g=Math.floor(r/7)+2,w=Math.ceil((r*4+4)/(g*2-2))*2;T.push(6);for(let _=y-7;T.length<g;_-=w)T.splice(1,0,_)}for(let g=0;g<T.length;g++)for(let w=0;w<T.length;w++)if(!(g===0&&w===0||g===0&&w===T.length-1||g===T.length-1&&w===0))for(let _=-2;_<=2;_++)for(let M=-2;M<=2;M++)x(T[g]+M,T[w]+_,Math.max(Math.abs(M),Math.abs(_))!==1);let I=g=>{let w=Fr[t]<<3|g,_=w;for(let S=0;S<10;S++)_=_<<1^(_>>>9)*1335;let M=(w<<10|_)^21522,A=S=>(M>>>S&1)!==0;for(let S=0;S<=5;S++)x(8,S,A(S));x(8,7,A(6)),x(8,8,A(7)),x(7,8,A(8));for(let S=9;S<15;S++)x(14-S,8,A(S));for(let S=0;S<8;S++)x(y-1-S,8,A(S));for(let S=8;S<15;S++)x(8,y-15+S,A(S));x(8,y-8,!0)};if(I(0),r>=7){let g=r;for(let _=0;_<12;_++)g=g<<1^(g>>>11)*7973;let w=r<<12|g;for(let _=0;_<18;_++){let M=(w>>>_&1)!==0,A=y-11+_%3,S=Math.floor(_/3);x(A,S,M),x(S,A,M)}}let P=0;for(let g=y-1;g>=1;g-=2){g===6&&(g=5);for(let w=0;w<y;w++)for(let _=0;_<2;_++){let M=g-_,S=(g+1&2)===0?y-1-w:w;!C[S][M]&&P<v.length*8&&(b[S][M]=(v[P>>>3]>>>7-(P&7)&1)!==0,P++)}}let L=g=>{for(let w=0;w<y;w++)for(let _=0;_<y;_++){if(C[w][_])continue;let M;switch(g){case 0:M=(_+w)%2===0;break;case 1:M=w%2===0;break;case 2:M=_%3===0;break;case 3:M=(_+w)%3===0;break;case 4:M=(Math.floor(_/3)+Math.floor(w/2))%2===0;break;case 5:M=_*w%2+_*w%3===0;break;case 6:M=(_*w%2+_*w%3)%2===0;break;default:M=((_+w)%2+_*w%3)%2===0}M&&(b[w][_]=!b[w][_])}},R=Number.isInteger(e.mask)?e.mask:-1;if(R<0){let g=1/0;for(let w=0;w<8;w++){L(w),I(w);let _=Nr(b,y);_<g&&(g=_,R=w),L(w)}}return L(R),I(R),{version:r,size:y,mask:R,modules:b}}function Nr(n,e){let t=0,i=[];for(let o=0;o<e;o++)i.push(n[o]);for(let o=0;o<e;o++)i.push(n.map(a=>a[o]));for(let o of i){let a=1;for(let c=1;c<=e;c++)c<e&&o[c]===o[c-1]?a++:(a>=5&&(t+=a-2),a=1);let l=o.map(c=>c?"1":"0").join("");for(let c of["10111010000","00001011101"])for(let p=l.indexOf(c);p>=0;p=l.indexOf(c,p+1))t+=40}let r=0;for(let o=0;o<e;o++)for(let a=0;a<e;a++)if(n[o][a]&&r++,a<e-1&&o<e-1){let l=n[o][a];l===n[o][a+1]&&l===n[o+1][a]&&l===n[o+1][a+1]&&(t+=3)}let s=e*e;return t+=Math.floor(Math.abs(r*20-s*10)/s)*10,t}function fn(n,e,{px:t=4,dark:i="#000",light:r="#fff",ecl:s="M"}={}){let o=Ut(e,{ecl:s}),a=o.size+8;n.width=n.height=a*t;let l=n.getContext("2d");l.fillStyle=r,l.fillRect(0,0,a*t,a*t),l.fillStyle=i;for(let c=0;c<o.size;c++)for(let p=0;p<o.size;p++)o.modules[c][p]&&l.fillRect((p+4)*t,(c+4)*t,t,t);return o}function Y(n,e){let t=new Error(`@displayxr/inline3d/call: ${e}`);return t.code=n,t}async function Bt(n){let e=await globalThis.crypto.subtle.digest("SHA-256",new TextEncoder().encode(String(n)));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}var Qe="wss://signal.displayxr.org",un=Object.freeze([Qe,"wss://dxr-signal.displayxr.workers.dev"]),pn=["bad-room","bad-id","bad-version","bad-key","origin-not-allowed","blocked"];function fe(n=Qe,e={}){if(!n||typeof n!="string")throw Y("no-signaling-url","dxrSignaling(url): url must be a ws:// or wss:// string (omit it for the hosted DisplayXR server)");let t=c=>String(c).replace(/\/+$/,""),i=t(n),r=e.WebSocket||globalThis.WebSocket,s=e.pingMs||2e4,o=Array.isArray(e.aliases)?e.aliases.filter(c=>typeof c=="string"&&c).map(t):un.includes(i)?[...un]:[],a=[i,...o.filter(c=>c!==i)],l=0;return{name:"dxr",url:i,async join(c,p){let h=`k=${await Bt(c)}${typeof e.key=="string"&&e.key?`&key=${encodeURIComponent(e.key)}`:""}`,d=L=>`${a[L]}/v1/connect?${h}`,m=null,u=!1,v=0,y=null,b=new Set,C=[],x=L=>O(L,a.length),O=(L,R)=>new Promise((g,w)=>{let _=!1,M=!1,A=!1,S=new r(d(l));m=S;let F=z=>{if(!_){_=!0;try{S.close()}catch{}w(z)}};S.onopen=()=>{A=!0,S.send(JSON.stringify({t:"join",v:1,room:c,id:p.id,max:p.maxPeers}))},S.onmessage=z=>{let k;try{k=JSON.parse(typeof z.data=="string"?z.data:String(z.data))}catch{return}switch(k.t){case"welcome":{v=0;let j=Array.isArray(k.peers)?k.peers.filter($=>typeof $=="string"):[];clearInterval(y),y=setInterval(()=>T({t:"ping"}),s);let me=C;C=[];for(let $ of me)T($);if(L){let $=new Set(j);for(let Z of b)$.has(Z)||p.onPeerLeft?.(Z);b=$,p.onReconnect?.(j)}else b=new Set(j);_=!0,M=!0,g({id:k.id,peers:j,iceServers:Array.isArray(k.iceServers)?k.iceServers:void 0,max:k.max,tier:k.tier==="key"?"key":"anon",key:typeof k.key=="string"?k.key:void 0,turn:k.turn&&typeof k.turn=="object"?k.turn:void 0});break}case"full":u=!0,F(Y("room-full",`this call is full (${k.max} participants)`));break;case"expired":{u=!0,clearInterval(y);let j=Y("expired","this room has reached its lifetime on the signalling server");_?p.onDisconnect?.(j):F(j);break}case"error":if(!_&&pn.includes(k.code))u=!0,F(Y(k.code,k.message||k.code));else if(!_&&(k.code==="rate-limited"||k.code==="quota")){let j=Y(k.code,k.message||k.code);j.retryMs=k.retryMs>0?k.retryMs:0,F(j)}else!_&&k.code==="id-taken"&&F(Y("id-taken","peer id still held; retrying"));break;case"peer-joined":typeof k.id=="string"&&!b.has(k.id)&&(b.add(k.id),p.onPeerJoined?.(k.id));break;case"peer-left":typeof k.id=="string"&&(b.delete(k.id),p.onPeerLeft?.(k.id));break;case"signal":typeof k.from=="string"&&p.onSignal?.(k.from,k.data);break}},S.onerror=()=>{if(!A&&!_&&R>1){_=!0,l=(l+1)%a.length,O(L,R-1).then(g,w);return}F(Y("signaling-unreachable",`cannot reach ${a[l]}`))},S.onclose=()=>{clearInterval(y),F(Y("signaling-closed","signalling closed before joining")),M&&!u&&m===S&&I()}}),T=L=>{m&&m.readyState===1?m.send(JSON.stringify(L)):u||C.push(L)},I=()=>{p.onDisconnect?.();let L=()=>{u||x(!0).catch(R=>{if(u||R&&(R.code==="room-full"||pn.includes(R.code))){p.onDisconnect?.(R);return}setTimeout(L,Math.max(B(v++,{baseMs:500,maxMs:15e3}),R&&R.retryMs||0))})};setTimeout(L,B(v++,{baseMs:300,maxMs:15e3}))};return{...await x(!1),send:(L,R)=>T({t:"signal",to:L,data:R}),leave:()=>{if(!u){u=!0,clearInterval(y);try{m&&m.readyState===1&&m.send(JSON.stringify({t:"leave"})),m&&m.close(1e3,"leave")}catch{}}}}}}}var qt=Object.freeze({azure:"#4da3ff",violet:"#9b7bff",magenta:"#ff4fa3",sunset:"#ff7a45",amber:"#ffc23d",lime:"#9be15d",mint:"#35e0b0",ice:"#8fe3ff"}),gn=n=>typeof n=="string"&&qt[n.toLowerCase()]||n,_n=Object.freeze({accent:"--dxr-accent",ink:"--dxr-ink",shell:"--dxr-shell",danger:"--dxr-danger",radius:"--dxr-radius",font:"--dxr-font"}),De=Object.freeze({lobbyStartTitle:"Start a 3D call",lobbyJoinTitle:"Join the 3D call",lobbyFullTitle:"This call is full",lobbyLeftTitle:"You left the call",lobbyFullText:"It already has {maxPeers} participants.",lobbyText:"Check your framing below. Camera: {camera} \u2014 {kind}.",cameraDefault:"default",kindBusy:"busy (joining audio-only)",kindNone:"none (joining audio-only)",kindSbs:"sending 3D (side-by-side, {width}\xD7{height})",kindMono:"sending 2D ({width}\xD7{height})",liftOff:"Mono cameras: 2D (2D\u21923D is off).",liftChecking:"Mono cameras: checking 2D\u21923D\u2026",liftMissing:"Mono cameras: 2D\u21923D unavailable in this build.",liftNoProvider:"Mono cameras: 2D (no 2D\u21923D provider here).",liftNative:"Mono cameras: 2D\u21923D (native{provider}).",liftWeb:"Mono cameras: 2D\u21923D (in this page, WebGPU).",liftProven:"Mono cameras: 2D\u21923D.",liftUnproven:"Mono cameras: 2D\u21923D (confirmed on the first mono participant).",start:"Start 3D call",join:"Join call",rejoin:"Rejoin",retryCamera:"Retry camera",cameraSelect:"Camera",joining:"Joining\u2026",waitingTitle:"Waiting for others",waitingText:"Share this link (or scan the code). Anyone who opens it joins \u2014 keep it private.",inviteTitle:"Invite",inviteText:"Anyone with this link can join.",inviteLink:"Invite link",copyLink:"Copy link",copied:"Copied",pressCopy:"Press Ctrl/Cmd+C",qrLabel:"QR code of the invite link",banner2D:"You are seeing this call in 2D.",bannerLink:"View in 3D with DisplayXR Browser",mute:"Mute microphone",unmute:"Unmute microphone",cameraOn:"Turn camera on",cameraOff:"Turn camera off",cameraRetry:"No camera \u2014 click to retry",cameraBusyRetry:"{cameraBusy} \u2014 click to retry",depth:"Depth",invite:"Invite",leave:"Leave call",connecting:"Connecting\u2026",reconnecting:"Reconnecting\u2026",leftCall:"Left the call",cameraOffPlate:"Camera off",noCamera:"No camera",unreachable:"Can't reach this participant \u2014 the network needs a relay (TURN)",cameraBusy:"Camera busy \u2014 in use by another app (e.g. eye tracking)",you:"You",badge3D:"3D",badge2D3D:"2D\u21923D",badge2D:"2D",badgePending:"\u2026"});function vn(n){let e={...De,...n&&typeof n=="object"?n:{}};return(t,i)=>{let r=typeof e[t]=="string"?e[t]:De[t]||t;if(i)for(let[s,o]of Object.entries(i))r=r.split(`{${s}}`).join(String(o));return r}}var mn="dxr-call-style",Vr=`
|
|
5
|
+
`,i=n.split(t),r=i.findIndex(d=>d.startsWith("m=video"));if(r<0)return n;let s=i.findIndex((d,m)=>m>r&&d.startsWith("m="));s<0&&(s=i.length);let o=i.slice(r,s),a=new Map,l=new Map;for(let d of o){let m=d.match(/^a=rtpmap:(\d+) ([\w-]+)\//);m&&a.set(m[1],m[2].toUpperCase());let u=d.match(/^a=fmtp:(\d+) apt=(\d+)/);u&&(l.has(u[2])||l.set(u[2],[]),l.get(u[2]).push(u[1]))}let c=i[r].split(" "),p=c.slice(3),f=[];for(let d of e)for(let m of p)if(a.get(m)===d&&!f.includes(m)){f.push(m);for(let u of l.get(m)||[])p.includes(u)&&!f.includes(u)&&f.push(u)}if(!f.length)return n;let h=p.filter(d=>!f.includes(d));return i[r]=[...c.slice(0,3),...f,...h].join(" "),i.join(t)}var Pi=Object.freeze([{urls:"stun:stun.l.google.com:19302"}]),hr=4e3,fr=1e4,ur=2e4,pr=8e3,mr=1e4;function Te(n){let e=Number.isInteger(n)?n:le;return Math.max(2,Math.min(Li,e))}function Fi(n,e){return n<e}var ke=class{constructor({signaling:e,id:t,maxPeers:i,iceServers:r,RTCPeerConnection:s,log:o,unreachableMs:a}={}){this.unreachableMs=a>0?a:mr,this.signaling=e,this.id=t,this.maxPeers=Te(i),this.pageIce=r||null,this.iceServers=r||Pi,this.PC=s||globalThis.RTCPeerConnection,this.log=o||(()=>{}),this.peers=new Map,this.session=null,this.ready=!1,this._pending=[],this.stopped=!1,this.sendFormat="mono",this.localStream=null}get size(){return this.peers.size}async start({room:e,localStream:t,sendFormat:i,onPeer:r,onPeerLeft:s,onStream:o,onMessage:a,onPeerState:l,onRefused:c,onSignalingState:p,onGhost:f}){this.localStream=t,this.sendFormat=i||"mono",this.cb={onPeer:r,onPeerLeft:s,onStream:o,onMessage:a,onPeerState:l,onRefused:c,onSignalingState:p,onGhost:f};let h=u=>(...v)=>this.ready?u(...v):this._pending.push(()=>u(...v));this.session=await this.signaling.join(e,{id:this.id,maxPeers:this.maxPeers,onPeerJoined:h(u=>this._onPeerJoined(u)),onPeerLeft:h(u=>this._onPeerLeftSignaling(u)),onSignal:h((u,v)=>this._onSignal(u,v)),onDisconnect:u=>p?.(u?"closed":"reconnecting",u),onPeerUnreachable:h(u=>f?.(u,!0)),onPeerReachable:h(u=>f?.(u,!1)),onReconnect:h(u=>{p?.("connected");for(let v of u)this._onPeerJoined(v)})}),!this.pageIce&&this.session.iceServers&&this.session.iceServers.length&&(this.iceServers=[...Pi,...this.session.iceServers]);let d=this.session.peers||[];if(d.length>=this.maxPeers){this.session.leave();let u=new Error(`@displayxr/inline3d/call: this call is full (${this.maxPeers} participants)`);throw u.code="room-full",u}this.ready=!0;for(let u of d)this._onPeerJoined(u);let m=this._pending;this._pending=[];for(let u of m)u();return this.session}_onPeerJoined(e){if(this.stopped||e===this.id)return;let t=this.peers.get(e);if(t){t.absent=!1,t.state!=="connected"&&Fi(this.id,e)&&this._rebuild(t,"rejoined");return}if(this.peers.size>=this.maxPeers-1){this.log("refused",{peer:e,reason:"maxPeers",maxPeers:this.maxPeers}),this.cb.onRefused?.(e);return}let i=this._newRecord(e);this.cb.onPeer?.(e),i.offerer?this._build(i,1):i.waitTimer=setTimeout(()=>this._askRestart(i),pr)}_onPeerLeftSignaling(e){let t=this.peers.get(e);t&&(t.absent=!0,t.state!=="connected"&&this._drop(t,"left"))}_newRecord(e){let t={id:e,offerer:Fi(this.id,e),pc:null,builtAt:0,offerAt:0,dc:null,gen:0,state:"new",stream:null,attempts:0,iceRestarted:!1,absent:!1,pendingCandidates:[],timers:new Set,waitTimer:null,unreachable:!1,unreachTimer:null};return this.peers.set(e,t),this._armUnreachable(t),t}_build(e,t){this._closePc(e),e.gen=t,e.builtAt=Date.now(),e.iceRestarted=!1,e.pendingCandidates=[],e.stream=null;let i=new this.PC({iceServers:this.iceServers});e.pc=i;let r=i.createDataChannel("dxr-call",{negotiated:!0,id:0,ordered:!0});if(this._wireDc(e,r),e.offerer){let s=this.localStream?this.localStream.getTracks():[],o=s.find(p=>p.kind==="audio"),a=s.find(p=>p.kind==="video"),l=this.localStream?[this.localStream]:[];i.addTransceiver(o||"audio",{direction:"sendrecv",streams:l});let c=i.addTransceiver(a||"video",{direction:"sendrecv",streams:l});this._preferCodecs(c)}return i.onicecandidate=s=>{s.candidate&&this._signal(e,{kind:"candidate",candidate:s.candidate.toJSON?s.candidate.toJSON():s.candidate})},i.ontrack=s=>{if(e.stream||(e.stream=new MediaStream),!e.stream.getTracks().includes(s.track)){for(let o of e.stream.getTracks())o.kind===s.track.kind&&e.stream.removeTrack(o);e.stream.addTrack(s.track)}this.cb.onStream?.(e.id,e.stream)},i.onconnectionstatechange=()=>this._onConnState(e,i),this._arm(e,ur,()=>{e.pc===i&&i.connectionState!=="connected"&&this._fail(e,"connect-timeout")}),e.offerer&&this._offer(e).catch(s=>this.log("offer-error",{peer:e.id,err:String(s)})),this._setState(e,e.attempts>0?"reconnecting":"connecting"),i}async _offer(e,{iceRestart:t=!1}={}){let i=e.pc,r=await i.createOffer(t?{iceRestart:!0}:void 0);this._canPreferCodecs||(r.sdp=Ee(r.sdp)),await i.setLocalDescription(r),this._signal(e,{kind:"offer",sdp:i.localDescription.sdp})}async _onSignal(e,t){if(this.stopped||!t||typeof t!="object")return;let i=this.peers.get(e);if(!i&&(t.kind!=="offer"||(this._onPeerJoined(e),i=this.peers.get(e),!i)))return;let r=t.gen|0;try{switch(t.kind){case"offer":{if(i.offerer||(clearTimeout(i.waitTimer),r<i.gen))return;i.offerAt=Date.now(),(r>i.gen||!i.pc)&&this._build(i,r);let s=i.pc;await s.setRemoteDescription({type:"offer",sdp:t.sdp}),this._attachAnswererTracks(i);let o=await s.createAnswer();this._canPreferCodecs||(o.sdp=Ee(o.sdp)),await s.setLocalDescription(o),this._signal(i,{kind:"answer",sdp:s.localDescription.sdp}),this._flushCandidates(i);break}case"answer":if(!i.offerer||r!==i.gen||!i.pc||i.pc.signalingState!=="have-local-offer")return;await i.pc.setRemoteDescription({type:"answer",sdp:t.sdp}),this._flushCandidates(i);break;case"candidate":if(r!==i.gen||!i.pc)return;i.pc.remoteDescription?await i.pc.addIceCandidate(t.candidate).catch(()=>{}):i.pendingCandidates.push(t.candidate);break;case"restart":if(!i.offerer||i.pc&&i.state!=="connected"&&Date.now()-i.builtAt<5e3)return;this._rebuild(i,"peer-asked");break;case"bye":this._drop(i,"left");break}}catch(s){this.log("signal-error",{peer:e,kind:t.kind,err:String(s)})}}_flushCandidates(e){let t=e.pendingCandidates;e.pendingCandidates=[];for(let i of t)e.pc.addIceCandidate(i).catch(()=>{})}_attachAnswererTracks(e){let t=e.pc,i=this.localStream?this.localStream.getTracks():[];for(let r of t.getTransceivers()){let s=r.receiver&&r.receiver.track?r.receiver.track.kind:null;if(!s||r.sender.track)continue;let o=i.find(a=>a.kind===s);o&&(r.sender.replaceTrack(o).catch(()=>{}),this.localStream&&r.sender.setStreams&&r.sender.setStreams(this.localStream)),r.direction="sendrecv",s==="video"&&this._preferCodecs(r)}}_preferCodecs(e){let t=globalThis.RTCRtpReceiver&&RTCRtpReceiver.getCapabilities&&RTCRtpReceiver.getCapabilities("video");if(this._canPreferCodecs=!!(e&&e.setCodecPreferences&&t),!!this._canPreferCodecs)try{e.setCodecPreferences($e(t.codecs))}catch{this._canPreferCodecs=!1}}_onConnState(e,t){if(e.pc!==t)return;let i=t.connectionState;this.log("pc-state",{peer:e.id,state:i,gen:e.gen}),i==="connected"?(this._clearTimers(e),e.attempts=0,e.iceRestarted=!1,this._setState(e,"connected"),this.tuneSenders()):i==="disconnected"?(this._setState(e,"reconnecting"),this._arm(e,hr,()=>{e.pc===t&&t.connectionState!=="connected"&&this._fail(e,"disconnected")})):i==="failed"?this._fail(e,"failed"):i==="closed"&&!this.stopped&&this.peers.get(e.id)===e&&this._fail(e,"closed")}_fail(e,t){if(this.stopped||this.peers.get(e.id)!==e)return;if(e.absent)return this._drop(e,"left");if(this._setState(e,"reconnecting"),!e.offerer)return this._askRestart(e);let i=e.pc;if(i&&!e.iceRestarted&&i.connectionState!=="closed"&&i.signalingState!=="closed"){e.iceRestarted=!0,this.log("ice-restart",{peer:e.id,why:t,gen:e.gen}),this._offer(e,{iceRestart:!0}).catch(()=>this._rebuild(e,"ice-restart-failed")),this._arm(e,fr,()=>{e.pc===i&&i.connectionState!=="connected"&&this._rebuild(e,"ice-restart-timeout")});return}this._rebuild(e,t)}_rebuild(e,t){if(this.stopped||this.peers.get(e.id)!==e)return;this._clearTimers(e),this._closePc(e),this._setState(e,"reconnecting");let i=B(e.attempts++);this.log("redial",{peer:e.id,why:t,attempt:e.attempts,inMs:i}),this._arm(e,i,()=>this._build(e,e.gen+1))}_askRestart(e){if(this.stopped||this.peers.get(e.id)!==e||e.offerer)return;let t=Date.now();this._signal(e,{kind:"restart"}),this._arm(e,Math.max(3e3,B(e.attempts++)),()=>{e.state!=="connected"&&!(e.offerAt>=t)&&this._askRestart(e)})}_drop(e,t){this.peers.get(e.id)===e&&(this._clearTimers(e),clearTimeout(e.unreachTimer),clearTimeout(e.waitTimer),this._closePc(e),this.peers.delete(e.id),this._setState(e,"left"),this.cb.onPeerLeft?.(e.id,t),this.tuneSenders())}_closePc(e){if(e.dc){try{e.dc.close()}catch{}e.dc=null}if(e.pc){let t=e.pc;e.pc=null;try{t.close()}catch{}}}_arm(e,t,i){let r=setTimeout(()=>{e.timers.delete(r),i()},t);e.timers.add(r)}_clearTimers(e){for(let t of e.timers)clearTimeout(t);e.timers.clear()}_armUnreachable(e){e.unreachTimer||e.unreachable||(e.unreachTimer=setTimeout(()=>{e.unreachTimer=null,!(this.stopped||this.peers.get(e.id)!==e||e.state==="connected")&&(e.unreachable=!0,this.log("unreachable",{peer:e.id,afterMs:this.unreachableMs,pc:e.pc?e.pc.iceConnectionState:null}),this._setState(e,"unreachable"))},this.unreachableMs))}_setState(e,t){t==="connected"?(clearTimeout(e.unreachTimer),e.unreachTimer=null,e.unreachable=!1):(t==="connecting"||t==="reconnecting")&&(e.unreachable?t="unreachable":this._armUnreachable(e)),e.state!==t&&(e.state=t,this.cb.onPeerState?.(e.id,t))}_signal(e,t){this.session?.send(e.id,{...t,gen:e.gen})}_wireDc(e,t){e.dc=t,t.onopen=()=>this.cb.onMessage?.(e.id,{type:"__open"}),t.onmessage=i=>{let r;try{r=JSON.parse(i.data)}catch{return}if(r&&r.type==="bye")return this._drop(e,"left");this.cb.onMessage?.(e.id,r)}}send(e,t){let i=this.peers.get(e);return i&&i.dc&&i.dc.readyState==="open"?(i.dc.send(JSON.stringify(t)),!0):!1}broadcast(e){for(let t of this.peers.keys())this.send(t,e)}peerConnection(e){let t=this.peers.get(e);return t?t.pc:null}peerState(e){let t=this.peers.get(e);return t?t.state:null}async replaceTrack(e,t,i){i&&(this.localStream=i);for(let r of this.peers.values())if(r.pc)for(let s of r.pc.getTransceivers())(s.receiver&&s.receiver.track?s.receiver.track.kind:null)===e&&await s.sender.replaceTrack(t).catch(()=>{});await this.tuneSenders()}setSendFormat(e){return this.sendFormat=e,this.tuneSenders()}async tuneSenders(){let e=this.peers.size,t=Ve(this.sendFormat,e);for(let i of this.peers.values())if(i.pc){for(let r of i.pc.getSenders())if(!(!r.track||r.track.kind!=="video"))try{let s=r.getParameters();s.degradationPreference="maintain-resolution",(!s.encodings||!s.encodings.length)&&(s.encodings=[{}]),s.encodings[0].maxBitrate=t*1e3,await r.setParameters(s)}catch(s){this.log("setParameters-error",{peer:i.id,err:String(s)})}}return t}stop(){if(!this.stopped){this.broadcast({type:"bye"}),this.stopped=!0;for(let e of this.peers.values())this._clearTimers(e),clearTimeout(e.waitTimer),clearTimeout(e.unreachTimer),this._signal(e,{kind:"bye"}),this._closePc(e);this.peers.clear();try{this.session?.leave()}catch{}}}_debugKill(e){let t=this.peers.get(e);return!t||!t.pc?!1:(this._closePc(t),this._fail(t,"debug-kill"),!0)}};var ji={width:{ideal:1280},height:{ideal:720},frameRate:{ideal:30}},Dt={width:{ideal:3840},height:{ideal:1080},frameRate:{ideal:30}},gr=Object.freeze({echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0});function _r(n){return!!n&&(n.name==="NotReadableError"||n.name==="TrackStartError"||/in use|busy/i.test(n.message||""))}function vr(n){return!!n&&(n.name==="NotAllowedError"||n.name==="PermissionDeniedError"||n.name==="SecurityError")}function Wi(n){return n.length&&n.every(e=>e.busy)?"camera-busy":n.some(e=>e.denied)?"permission-denied":"no-camera"}function Lt(n){return/stereo|\b3d\b|\bsbs\b|dual/i.test(n||"")}async function Ni(n="auto",e={}){let t=e.mediaDevices||globalThis.navigator&&navigator.mediaDevices,i=e.log||(()=>{}),r=[],s=e.calibration||{};if(n&&typeof n=="object"&&typeof n.getVideoTracks=="function"){let m=n.getVideoTracks()[0],u=m?m.getSettings():{},v=e.format==="sbs"?"sbs":"mono";return{stream:n,format:v,width:u.width||0,height:u.height||0,deviceId:u.deviceId||null,label:m?m.label:"",owned:!1,skipped:r,calibration:s}}if(!t||!t.getUserMedia)throw Object.assign(new Error("getUserMedia is not available (insecure context?)"),{code:"no-camera"});let o=async m=>{let u=await t.getUserMedia({video:m,audio:!1}),v=u.getVideoTracks()[0],y=v?v.getSettings():{};if(!v||v.readyState==="ended"||!(y.width>0)||!(y.height>0))throw u.getTracks().forEach(C=>C.stop()),Object.assign(new Error("the camera opened but delivers no picture (0x0)"),{name:"NotReadableError"});let b=y.displayxrStereo&&y.displayxrStereo.layout==="side-by-side"?y.displayxrStereo:null;return{stream:u,track:v,width:y.width,height:y.height,deviceId:y.deviceId||null,label:v.label||"",stereo:b}},a=(m,u)=>{r.push({label:m,error:`${u.name}: ${u.message}`,busy:_r(u),denied:vr(u)}),i("camera-skip",{label:m,error:u.name})},l=m=>m&&m.stream.getTracks().forEach(u=>u.stop()),c=(m,u)=>({stream:m.stream,format:u,width:m.width,height:m.height,deviceId:m.deviceId,label:m.label,owned:!0,skipped:r,calibration:{rectified:!1,...u==="sbs"&&m.stereo?{rectified:!!m.stereo.rectified,...m.stereo.baselineMm>0?{baselineMm:m.stereo.baselineMm}:{},...m.stereo.horizontalFovDeg>0?{hfovDeg:m.stereo.horizontalFovDeg}:{}}:{},...s}});if(typeof n=="string"&&!["auto","stereo","mono"].includes(n)){let m;try{m=await o({deviceId:{exact:n},...Dt})}catch(u){throw a(n,u),Object.assign(new Error(`camera unavailable: ${u.message}`),{code:Wi(r),skipped:r})}return oe(m.width,m.height)?c(m,"sbs"):(l(m),c(await o({deviceId:{exact:n},...ji}),"mono"))}let p=new Set;if(n!=="mono"){let m=[];try{m=(await t.enumerateDevices()).filter(u=>u.kind==="videoinput"&&u.deviceId&&Lt(u.label))}catch{}for(let u of m){p.add(u.deviceId);let v=null;try{v=await o({deviceId:{exact:u.deviceId},...Dt})}catch(y){a(u.label,y);continue}if(oe(v.width,v.height))return i("camera-sbs",{label:v.label,width:v.width,height:v.height,direct:!0}),c(v,"sbs");l(v)}}let f=null;try{f=await o(ji)}catch(m){a("default",m)}if(n==="mono"&&f)return c(f,"mono");if(f&&oe(f.width,f.height))return c(f,"sbs");let h=[];try{h=(await t.enumerateDevices()).filter(m=>m.kind==="videoinput")}catch{}h.sort((m,u)=>Number(Lt(u.label))-Number(Lt(m.label)));for(let m of h){if(!m.deviceId||f&&m.deviceId===f.deviceId||p.has(m.deviceId))continue;let u=null;try{u=await o({deviceId:{exact:m.deviceId},...Dt})}catch(v){a(m.label,v);continue}if(oe(u.width,u.height))return l(f),i("camera-sbs",{label:u.label,width:u.width,height:u.height}),c(u,"sbs");l(u)}if(f)return n==="stereo"&&i("camera-no-stereo",{fallback:f.label}),c(f,"mono");let d=Wi(r);throw Object.assign(new Error(d==="camera-busy"?"every camera is in use by another app (e.g. eye tracking)":d==="permission-denied"?"camera access was denied":"no camera could be opened"),{code:d,skipped:r})}async function zi(n={}){let e=n.mediaDevices||globalThis.navigator&&navigator.mediaDevices;try{return(await e.getUserMedia({audio:{...gr},video:!1})).getAudioTracks()[0]||null}catch(t){return(n.log||(()=>{}))("mic-skip",{error:t&&t.name}),null}}function Ue(n,e,t,i,r,s,o,a,l,c,p){if(s<0||s+a>t||o<0)return-1;let f=0,h=0,d=0,m=a*l;for(let y=0;y<l;y++){let b=(r+y)*e+i,C=(o+y)*e+t+s;for(let x=0;x<a;x++){let I=n[C+x];f+=I,h+=I*I,d+=n[b+x]*I}}let u=f/m,v=h/m-u*u;return v<1?-1:(d/m-c*u)/(p*Math.sqrt(v))}function yr(n,e,t,i,r,s){let o=0,a=0;for(let p=0;p<s;p++){let f=(i+p)*e+t;for(let h=0;h<r;h++){let d=n[f+h];o+=d,a+=d*d}}let l=r*s,c=o/l;return{mean:c,std:Math.sqrt(Math.max(0,a/l-c*c))}}function At(n,e,t,i,r,s,o,{dMin:a,dMax:l,dyMax:c=2,uniq:p}={}){let f=e/2,{mean:h,std:d}=yr(n,e,i,r,s,o);if(d<6)return null;let m=-2,u=0,v=0,y=new Map,b=(R,g,w,_,M)=>{for(let A=_;A<=M;A++){let S=r+A;if(!(S<0||S+o>t))for(let F=R;F<=g;F+=w){let z=Ue(n,e,f,i,r,i-F,S,s,o,h,d);z>(y.get(F)??-2)&&y.set(F,z),z>m&&(m=z,u=F,v=A)}}},C=l-a>8;if(b(a,l,C?2:1,-c,c),C&&m>-1){let R=u,g=v;b(Math.max(a,R-2),Math.min(l,R+2),1,Math.max(-c,g-1),Math.min(c,g+1))}if(m<-1)return null;let x=-2,I=R=>{let g=-2;for(let w=-c;w<=c;w++){let _=r+w;if(!(_<0||_+o>t))for(let M=R-1;M<=R+1;M++)g=Math.max(g,Ue(n,e,f,i,r,i-M,_,s,o,h,d))}return g};for(let[R,g]of y){if(Math.abs(R-u)<3||g<=x)continue;let _=g>=(y.get(R-2)??-2)&&g>=(y.get(R+2)??-2)&&g>0?I(R):g;_>x&&(x=_)}if(l-a>12&&x>-2&&m-x<(p??.08))return null;let T=Ue(n,e,f,i,r,i-(u-1),r+v,s,o,h,d),O=Ue(n,e,f,i,r,i-(u+1),r+v,s,o,h,d),P=0,L=T-2*m+O;return T>-1&&O>-1&&L<0&&(P=Math.max(-.5,Math.min(.5,.5*(T-O)/L))),{d:u+P,dy:v,c:m}}function wr(n,e,t,i={}){let r=e/2,s=i.block||Math.max(8,Math.round(r/20)),o=i.step||Math.round(s*1.5),a=i.dMax??Math.round(r*.3),l=i.dMin??-Math.round(r*.05),c=Math.round(r*(i.roiX0??.15)),p=Math.round(r*(i.roiX1??.85))-s,f=Math.round(t*(i.roiY0??.05)),h=Math.round(t*(i.roiY1??.85))-s,d=[];for(let m=f;m<=h;m+=o)for(let u=c;u<=p;u+=o){let v=At(n,e,t,u,m,s,s,{dMin:l,dMax:a,dyMax:i.dyMax??2,uniq:i.uniq});v&&v.c>=(i.minNcc??.8)&&d.push({x:u,y:m,...v})}return d}function br(n,{tol:e=2,minFrac:t=.12,minBlocks:i=3}={}){if(!n.length)return null;let r=Math.max(i,Math.ceil(n.length*t)),s=n.map(o=>o.d).sort((o,a)=>a-o);for(let o of s){let a=n.filter(l=>Math.abs(l.d-o)<=e);if(a.length>=r){let l=a.map(c=>c.d).sort((c,p)=>c-p);return{d:l[l.length>>1],members:a}}}return null}function xr(n,e){let t=Math.min(...n.map(l=>l.y)),r=n.filter(l=>l.y<=t+2*e).map(l=>l.x),s=Math.min(...r),o=Math.max(...r)+e,a=o-s;return{x:(s+o)/2,y:t+.4*1.3*a}}function Ot(n,e,t,i={}){let r=e/2,s=i.block||Math.max(8,Math.round(r/20)),o=i.dMax??Math.round(r*.3),a=i.dMin??-Math.round(r*.05),l=i.focus||null,c="focus",p=0,f=null;if(!l){let C=wr(n,e,t,{...i,block:s,dMax:o,dMin:a});p=C.length;let x=br(C,i);if(!x)return null;l=xr(x.members,s),f=x.d,c="mode"}let h=Math.round(s*(i.refineW??3)),d=Math.round(s*(i.refineH??1.5)),m=Math.round(Math.max(0,Math.min(r-h,l.x-h/2))),u=Math.round(Math.max(0,Math.min(t-d,l.y-d/2))),v=f===null?a:Math.max(a,Math.floor(f)-4),y=f===null?o:Math.min(o,Math.ceil(f)+4),b=At(n,e,t,m,u,h,d,{dMin:v,dMax:y,dyMax:i.dyMax??2});return b&&b.c>=(i.minNcc??.8)?{d:b.d,x:l.x,y:l.y,c:b.c,method:c,blocks:p}:f!==null?{d:f,x:l.x,y:l.y,c:0,method:c,blocks:p}:null}function Be(n,e){let t=new Uint8Array(e);for(let i=0,r=0;i<e;i++,r+=4)t[i]=n[r]*77+n[r+1]*150+n[r+2]*29>>8;return t}function qe({n=3}={}){let e=[],t={value:null,push(i){if(i===null||!Number.isFinite(i))return t.value;e.push(i),e.length>n&&e.shift();let r=[...e].sort((s,o)=>s-o);return t.value=r[r.length>>1],t.value},reset(){e.length=0,t.value=null}};return t}function Hi(n,e,t,i,r,s){let o=new Float32Array(r*s);for(let a=0;a<s;a++)for(let l=0;l<r;l++)o[a*r+l]=n[(i+a)*e+t+l];return o}function Sr(n,e,t,i,r,s,o,a,l,c){let p=e/2,f=r*s,h=0,d=0;for(let b=0;b<f;b++)h+=i[b],d+=i[b]*i[b];h/=f;let m=Math.sqrt(Math.max(1e-6,d/f-h*h)),u=-2,v=o,y=a;for(let b=Math.max(0,a-c);b<=Math.min(t-s,a+c);b++)for(let C=Math.max(0,o-l);C<=Math.min(p-r,o+l);C++){let x=0,I=0,T=0;for(let R=0;R<s;R++){let g=(b+R)*e+C;for(let w=0;w<r;w++){let _=n[g+w];x+=_,I+=_*_,T+=_*i[R*r+w]}}let O=x/f,P=I/f-O*O;if(P<1)continue;let L=(T/f-O*h)/(Math.sqrt(P)*m);L>u&&(u=L,v=C,y=b)}return{x:v,y,c:u}}function Ce({fullEveryMs:n=2e3,dWin:e=4,rx:t=12,ry:i=8,minTrackNcc:r=.75,jump:s=8}={}){let o=null,a=null;return{measure(c,p,f,h,d={}){let m=p/2,u=d.block||Math.max(8,Math.round(m/20)),v=Math.round(u*3),y=Math.round(u*1.5),b=null;if(o&&o.w===v&&o.h===y){let O=Sr(c,p,f,o.tpl,v,y,o.x,o.y,t,i);if(O.c>=r){let P=At(c,p,f,O.x,O.y,v,y,{dMin:Math.floor(o.d)-e,dMax:Math.ceil(o.d)+e,dyMax:2});P&&P.c>=.8&&(b={m:P,f:O})}}let C=({m:O,f:P})=>(o={...o,x:P.x,y:P.y,d:O.d,tpl:Hi(c,p,P.x,P.y,v,y)},{d:O.d,x:P.x+v/2,y:P.y+y/2,c:O.c,method:"track",blocks:0});if(b&&h-o.at<n)return C(b);let x=Ot(c,p,f,d);if(b&&(!x||Math.abs(x.d-b.m.d)>s)){let O=x&&a&&Math.abs(a.d-x.d)<=3;if(a=x&&!O?{d:x.d}:null,!O)return o.at=h,C(b)}else a=null;if(!x)return o=null,null;let I=Math.round(Math.max(0,Math.min(m-v,x.x-v/2))),T=Math.round(Math.max(0,Math.min(f-y,x.y-y/2)));return o={x:I,y:T,d:x.d,tpl:Hi(c,p,I,T,v,y),w:v,h:y,at:h},x},reset(){o=null,a=null}}}function Vi(n,e,t,i,r,s){let o=Math.max(1,s|0),a=Math.floor(i/o);a-=a&1;let l=Math.floor(r/o),c=new Uint8Array(a*l);if(o<=2){let h=o*o;for(let d=0;d<l;d++)for(let m=0;m<a;m++){let u=0;for(let v=0;v<o;v++){let y=e+(d*o+v)*t+m*o;for(let b=0;b<o;b++)u+=n[y+b]}c[d*a+m]=u/h|0}return{img:c,w:a,h:l}}let p=o>>2,f=3*o>>2;for(let h=0;h<l;h++){let d=e+(h*o+p)*t,m=e+(h*o+f)*t;for(let u=0;u<a;u++){let v=u*o+p,y=u*o+f;c[h*a+u]=n[d+v]+n[d+y]+n[m+v]+n[m+y]>>2}}return{img:c,w:a,h:l}}var $i="http://displayxr.org/ns/stereo/1.0/",Xe="http://ns.adobe.com/xap/1.0/\0";function Je(n={}){let e=i=>typeof i=="number"&&Number.isFinite(i)?i:null,t=n.layout==="sbs"||n.layout==="side-by-side"?"sbs":"mono";return{layout:t,columns:t==="sbs"?2:1,rows:1,convergencePx:e(n.convergencePx),baselineMm:e(n.baselineMm),horizontalFovDeg:e(n.horizontalFovDeg),rectified:n.rectified===!0?!0:n.rectified===!1?!1:null,eyeWidth:e(n.eyeWidth),eyeHeight:e(n.eyeHeight),software:typeof n.software=="string"&&n.software?n.software:null}}var Mr=n=>String(n).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<"),he=n=>Math.round(n*1e3)/1e3;function Ui(n){let e=Je(n),t=[["Layout",e.layout==="sbs"?"side-by-side":"mono"],["Columns",e.columns],["Rows",e.rows],["ConvergencePx",e.convergencePx===null?null:he(e.convergencePx)],["BaselineMm",e.baselineMm===null?null:he(e.baselineMm)],["HorizontalFovDeg",e.horizontalFovDeg===null?null:he(e.horizontalFovDeg)],["Rectified",e.rectified===null?null:e.rectified?"True":"False"],["EyeWidth",e.eyeWidth],["EyeHeight",e.eyeHeight],["Software",e.software]].filter(([,i])=>i!=null).map(([i,r])=>` dxr:${i}="${Mr(r)}"`).join("");return`<?xpacket begin="\uFEFF" id="W5M0MpCehiHzreSzNTczkc9d"?><x:xmpmeta xmlns:x="adobe:ns:meta/"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:dxr="${$i}"${t}/></rdf:RDF></x:xmpmeta><?xpacket end="w"?>`}function Pt(n){if(typeof n!="string"||!n.includes($i))return null;let e=o=>{let a=new RegExp(`\\bdxr:${o}="([^"]*)"`).exec(n);if(a)return a[1];let l=new RegExp(`<dxr:${o}>([^<]*)</dxr:${o}>`).exec(n);return l?l[1]:null},t=o=>{let a=e(o);return a===null||a===""||!Number.isFinite(+a)?null:+a},i=e("Rectified"),r=e("Layout"),s=e("Software");return Je({layout:r==="side-by-side"||r==="sbs"?"sbs":"mono",convergencePx:t("ConvergencePx"),baselineMm:t("BaselineMm"),horizontalFovDeg:t("HorizontalFovDeg"),rectified:i===null?null:/^true$/i.test(i),eyeWidth:t("EyeWidth"),eyeHeight:t("EyeHeight"),software:s===null?null:s.replace(/"/g,'"').replace(/</g,"<").replace(/&/g,"&")})}var Ge=n=>new TextEncoder().encode(n),It=n=>new TextDecoder().decode(n),Bi=n=>n.length>4&&n[0]===255&&n[1]===216;function*qi(n){let e=2;for(;e+4<=n.length;){if(n[e]!==255)return;let t=n[e+1];if(t===216||t>=208&&t<=215||t===1||t===255){e+=t===255?1:2;continue}if(t===218||t===217)return;let i=n[e+2]<<8|n[e+3];if(i<2||e+2+i>n.length)return;yield{marker:t,start:e,end:e+2+i,data:n.subarray(e+4,e+2+i)},e+=2+i}}function Xi(n,e){if(n.length<e.length)return!1;for(let t=0;t<e.length;t++)if(n[t]!==e.charCodeAt(t))return!1;return!0}function Gi(n,e){if(!Bi(n))throw new TypeError("jpegWithXmp: not a JPEG");let t=new Uint8Array([...Ge(Xe),...Ge(e)]),i=t.length+2;if(i>65535)throw new RangeError("jpegWithXmp: XMP packet too large for one APP1 segment");let r=new Uint8Array(4+t.length);r[0]=255,r[1]=225,r[2]=i>>8,r[3]=i&255,r.set(t,4);let s=2,o=null;for(let p of qi(n)){if(p.marker===225&&Xi(p.data,Xe)){o=p;break}if(p.marker===224||p.marker===225)s=p.end;else break}let[a,l]=o?[o.start,o.end]:[s,s],c=new Uint8Array(n.length-(l-a)+r.length);return c.set(n.subarray(0,a),0),c.set(r,a),c.set(n.subarray(l),a+r.length),c}function Ft(n){if(!Bi(n))return null;for(let e of qi(n))if(e.marker===225&&Xi(e.data,Xe))return It(e.data.subarray(Xe.length));return null}var Ji=n=>Pt(Ft(n)),H={EBML:440786851,Segment:408125543,Tags:307544935,Tag:29555,Targets:25536,SimpleTag:26568,TagName:17827,TagString:17543},Er=n=>n.length>4&&n[0]===26&&n[1]===69&&n[2]===223&&n[3]===163;function Ki(n){let e=[];for(let t=n;t>0;t=Math.floor(t/256))e.unshift(t%256);return e}function Yi(n,e=0){let t=e;if(!t)for(t=1;t<8&&n>2**(7*t)-2;t++);let i=new Array(t).fill(0),r=n;for(let s=t-1;s>=1;s--)i[s]=r%256,r=Math.floor(r/256);return i[0]=128>>t-1|r,i}function jt(n,e){let t=n[e],i=t>=128?1:t>=64?2:t>=32?3:t>=16?4:0;if(!i||e+i>n.length)return null;let r=0;for(let s=0;s<i;s++)r=r*256+n[e+s];return{id:r,width:i}}function Re(n,e){let t=n[e],i=1;for(;i<=8&&!(t&128>>i-1);)i++;if(i>8||e+i>n.length)return null;let r=t&255>>i,s=r===127>>i-1;for(let o=1;o<i;o++)r=r*256+n[e+o],n[e+o]!==255&&(s=!1);return{size:r,width:i,unknown:s}}function de(n,e){return[...Ki(n),...Yi(e.length),...e]}function kr(n){let e=[];for(let[i,r]of Object.entries(n))r!=null&&e.push(...de(H.SimpleTag,[...de(H.TagName,[...Ge(String(i))]),...de(H.TagString,[...Ge(String(r))])]));let t=de(H.Tag,[...de(H.Targets,[]),...e]);return new Uint8Array(de(H.Tags,t))}function Zi(n){let e=Je(n);return{DXR_LAYOUT:e.layout==="sbs"?"side-by-side":"mono",DXR_COLUMNS:String(e.columns),DXR_ROWS:String(e.rows),DXR_CONVERGENCE_PX:e.convergencePx===null?null:String(he(e.convergencePx)),DXR_BASELINE_MM:e.baselineMm===null?null:String(he(e.baselineMm)),DXR_HFOV_DEG:e.horizontalFovDeg===null?null:String(he(e.horizontalFovDeg)),DXR_RECTIFIED:e.rectified===null?null:e.rectified?"true":"false",DXR_EYE_WIDTH:e.eyeWidth===null?null:String(e.eyeWidth),DXR_EYE_HEIGHT:e.eyeHeight===null?null:String(e.eyeHeight),DXR_SOFTWARE:e.software}}function Tr(n){if(!n||!("DXR_LAYOUT"in n))return null;let e=t=>n[t]===void 0||n[t]===""||!Number.isFinite(+n[t])?null:+n[t];return Je({layout:n.DXR_LAYOUT==="side-by-side"?"sbs":"mono",convergencePx:e("DXR_CONVERGENCE_PX"),baselineMm:e("DXR_BASELINE_MM"),horizontalFovDeg:e("DXR_HFOV_DEG"),rectified:n.DXR_RECTIFIED===void 0?null:n.DXR_RECTIFIED==="true",eyeWidth:e("DXR_EYE_WIDTH"),eyeHeight:e("DXR_EYE_HEIGHT"),software:n.DXR_SOFTWARE??null})}function Qi(n){if(!Er(n))return null;let e=Re(n,4);if(!e)return null;let t=4+e.width+e.size;for(;t<n.length;){let i=jt(n,t);if(!i)return null;let r=Re(n,t+i.width);if(!r)return null;let s=t+i.width+r.width;if(i.id===H.Segment)return{sizeAt:t+i.width,sizeWidth:r.width,unknown:r.unknown,dataStart:s,size:r.size};if(r.unknown)return null;t=s+r.size}return null}function en(n,e){let t=Qi(n);if(!t)throw new TypeError("webmWithTags: not a WebM/Matroska file (no Segment)");let i=kr(e);if(t.unknown){let p=new Uint8Array(n.length+i.length);return p.set(n,0),p.set(i,n.length),p}let r=Math.min(n.length,t.dataStart+t.size),s=r-t.dataStart+i.length,o=s<=2**(7*t.sizeWidth)-2,a=Yi(s,o?t.sizeWidth:8),l=new Uint8Array(t.sizeAt+a.length+(r-t.dataStart)+i.length+(n.length-r));l.set(n.subarray(0,t.sizeAt),0),l.set(a,t.sizeAt);let c=t.sizeAt+a.length;return l.set(n.subarray(t.dataStart,r),c),c+=r-t.dataStart,l.set(i,c),c+=i.length,l.set(n.subarray(r),c),l}function tn(n,e,t){let i={},r=(s,o,a)=>{let l=s;for(;l<o;){let c=jt(n,l);if(!c)return;let p=Re(n,l+c.width);if(!p||p.unknown)return;let f=l+c.width+p.width;a(c.id,f,Math.min(o,f+p.size)),l=f+p.size}};return r(e,t,(s,o,a)=>{s===H.Tag&&r(o,a,(l,c,p)=>{if(l!==H.SimpleTag)return;let f=null,h=null;r(c,p,(d,m,u)=>{d===H.TagName?f=It(n.subarray(m,u)):d===H.TagString&&(h=It(n.subarray(m,u)))}),f!==null&&(i[f]=h??"")})}),i}function Cr(n){let e=Qi(n);if(!e)return null;let t=e.unknown?n.length:Math.min(n.length,e.dataStart+e.size),i=null,r=e.dataStart;for(;r<t;){let s=jt(n,r);if(!s)break;let o=Re(n,r+s.width);if(!o)break;let a=r+s.width+o.width;if(s.id===H.Tags&&!o.unknown&&(i={...i||{},...tn(n,a,Math.min(t,a+o.size))}),o.unknown){i=i||Rr(n,t);break}r=a+o.size}return i}function Rr(n,e){let t=Ki(H.Tags);for(let i=e-t.length-1;i>=0;i--){if(n[i]!==t[0]||n[i+1]!==t[1]||n[i+2]!==t[2]||n[i+3]!==t[3])continue;let r=Re(n,i+4);if(r&&!r.unknown&&i+4+r.width+r.size===e)return tn(n,i+4+r.width,e)}return null}var nn=n=>Tr(Cr(n));var ee="[inline3d/camera]",on="inline3d-camera/1",Dr=200,Lr=240,Ar=4e3,Or=4,Ir=1500,Pr=2e4,Fr=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm","video/mp4"],Ke=()=>typeof document<"u"&&document&&typeof document.createElement=="function",rn=()=>{let n=new Date,e=t=>String(t).padStart(2,"0");return`${n.getFullYear()}${e(n.getMonth()+1)}${e(n.getDate())}-${e(n.getHours())}${e(n.getMinutes())}${e(n.getSeconds())}`},jr=n=>/jpe?g/.test(n)?"jpg":/png/.test(n)?"png":/webp/.test(n)?"webp":/mp4/.test(n)?"mp4":/webm/.test(n)?"webm":"bin";function Ye(n,e,t){return`${String(n||"capture").replace(/[^\w.-]+/g,"-").replace(/^-+|-+$/g,"")||"capture"}${e==="sbs"?"_2x1":""}.${jr(t)}`}var K=(n,e,t={})=>Object.assign(new Error(`${ee} ${n}`),{code:e,...t});function sn(n,e=Ar){return n?(n.readyState||0)>=2&&n.videoWidth?Promise.resolve():new Promise((t,i)=>{let r=!1,s=()=>{r||(n.readyState||0)<2||!n.videoWidth||(r=!0,clearTimeout(o),n.removeEventListener("loadeddata",s),n.removeEventListener("playing",s),n.removeEventListener("resize",s),t())},o=setTimeout(()=>{r||(r=!0,i(K("the camera delivered no frame in time","no-frame")))},e);n.addEventListener("loadeddata",s),n.addEventListener("playing",s),n.addEventListener("resize",s),n.play?.().catch(()=>{})}):Promise.reject(K("no video element (no document?)","no-frame"))}function an(n,e,t=Lr){let i=n.videoWidth,r=n.videoHeight;if(!i||!r||(n.readyState||0)<2)return null;let s=Math.min(1,t/(i/2)),o=Math.max(2,Math.round(i*s/2)*2),a=Math.max(2,Math.round(r*s));(e.width!==o||e.height!==a)&&(e.width=o,e.height=a);let l=e.getContext("2d",{willReadFrequently:!0});try{return l.drawImage(n,0,0,o,a),{img:Be(l.getImageData(0,0,o,a).data,o*a),w:o,h:a,scale:o/i}}catch{return null}}var Wt=class{constructor(e,{log:t=null}={}){this.format=e.format,this.stream=e.stream,this.width=e.width||0,this.height=e.height||0,this.deviceId=e.deviceId||null,this.label=e.label||"",this.owned=!!e.owned,this.skipped=Object.freeze([...e.skipped||[]]),this.calibration=Object.freeze({...e.calibration||{}});let i=this.calibration;this.stereo=this.format==="sbs"?Object.freeze({rectified:!!i.rectified,baselineMm:i.baselineMm>0?i.baselineMm:null,horizontalFovDeg:i.hfovDeg>0?i.hfovDeg:null}):null,this.state="live",this._log=t,this._listeners=new Map,this._scratch=null,this._views=new Set,this.video=null,Ke()&&(this.video=Object.assign(document.createElement("video"),{muted:!0,playsInline:!0,autoplay:!0}),this.video.srcObject=this.stream,this.video.play?.().catch(()=>{})),this._onEnded=()=>this._ended("ended");for(let r of this.stream.getVideoTracks())r.addEventListener?.("ended",this._onEnded)}get eyeWidth(){return this.format==="sbs"?this.width/2:this.width}log(e,t={}){this._log&&this._log(e,t)}on(e,t){if(typeof t!="function")throw new TypeError(`${ee} on() takes a function`);return this._listeners.has(e)||this._listeners.set(e,new Set),this._listeners.get(e).add(t),()=>this._listeners.get(e)?.delete(t)}off(e,t){this._listeners.get(e)?.delete(t)}_emit(e,t){for(let i of[...this._listeners.get(e)||[]])try{i(t)}catch(r){console.error(`${ee} '${e}' listener threw`,r)}}_ended(e){this.state==="live"&&(this.state="ended",this.log("ended",{reason:e}),this._emit("ended",{reason:e}))}async measureConvergence(){if(this.format!=="sbs"||!this.video||!Ke())return null;try{await sn(this.video)}catch{return null}this._scratch=this._scratch||document.createElement("canvas");let e=an(this.video,this._scratch);if(!e)return null;let t=Ce().measure(e.img,e.w,e.h,0);return t?t.d/e.scale:null}_meta(e,t=this.width,i=this.height){let r=this.stereo;return{layout:this.format,convergencePx:e,baselineMm:r?r.baselineMm:null,horizontalFovDeg:r?r.horizontalFovDeg:null,rectified:r?r.rectified:null,eyeWidth:this.format==="sbs"?t/2:t,eyeHeight:i,software:on}}async capturePhoto({type:e="image/jpeg",quality:t=.92,name:i,convergencePx:r}={}){if(this.state==="closed")throw K("the camera is closed","closed");if(!this.video||!Ke())throw K("capturePhoto needs a document","no-frame");await sn(this.video);let s=this.video.videoWidth,o=this.video.videoHeight,a=typeof r=="number"&&Number.isFinite(r)?r:await this.measureConvergence(),l=document.createElement("canvas");l.width=s,l.height=o,l.getContext("2d").drawImage(this.video,0,0,s,o);let c=await new Promise((d,m)=>l.toBlob(u=>u?d(u):m(K("toBlob produced nothing","encode-failed")),e,t)),p=this._meta(a,s,o),f=null;(c.type==="image/jpeg"||/jpe?g/.test(e))&&(f=Ui(p),c=new Blob([Gi(new Uint8Array(await c.arrayBuffer()),f)],{type:"image/jpeg"}));let h={blob:c,type:c.type||e,width:s,height:o,layout:this.format,convergencePx:a,stereo:this.stereo,suggestedName:Ye(i||`photo-${rn()}`,this.format,c.type||e),xmp:f};return this.log("photo",{width:s,height:o,layout:this.format,convergencePx:a,bytes:c.size,name:h.suggestedName}),h}record({mimeType:e,mono:t=!1,audio:i=null,videoBitsPerSecond:r,timesliceMs:s=1e3,name:o,fps:a=30}={}){if(this.state==="closed")throw K("the camera is closed","closed");if(typeof MediaRecorder!="function")throw K("MediaRecorder is not available here","unsupported");let l=e||Fr.find(g=>typeof MediaRecorder.isTypeSupported!="function"||MediaRecorder.isTypeSupported(g))||"";if(l&&typeof MediaRecorder.isTypeSupported=="function"&&!MediaRecorder.isTypeSupported(l))throw K(`${l} is not a supported recording type here`,"unsupported");let c=[...this.stream.getVideoTracks()],p=i&&typeof i.getAudioTracks=="function"?i.getAudioTracks():i&&i.kind==="audio"?[i]:[];c.push(...p);let f=new MediaStream(c),h={...l?{mimeType:l}:{},...r?{videoBitsPerSecond:r}:{}},d=new MediaRecorder(f,h),m=[];d.ondataavailable=g=>g.data&&g.data.size&&m.push(g.data);let u=null,v=[],y=null,b=0,C=!!t&&this.format==="sbs"&&Ke()&&this.video;if(C){y=document.createElement("canvas");let g=()=>{b=requestAnimationFrame(g);let _=this.video,M=_.videoWidth,A=_.videoHeight;!M||!A||(_.readyState||0)<2||((y.width!==M/2||y.height!==A)&&(y.width=M/2,y.height=A),y.getContext("2d").drawImage(_,0,0,M/2,A,0,0,M/2,A))};g();let w=y.captureStream(a);for(let _ of p)w.addTrack(_);u=new MediaRecorder(w,h),u.ondataavailable=_=>_.data&&_.data.size&&v.push(_.data)}let x=performance.now(),I=[],T=this.format==="sbs"?setInterval(()=>this.measureConvergence().then(g=>g!==null&&I.push(g)),1500):0;this.measureConvergence().then(g=>g!==null&&I.push(g)),d.start(s),u?.start(s),this.log("record-start",{mimeType:l,mono:C,audio:p.length});let O=(g,w)=>new Promise(_=>{if(!g||g.state==="inactive")return _(w);g.onstop=()=>_(w),g.stop()}),P=o||`clip-${rn()}`,L=this;return{get state(){return d.state},get mimeType(){return d.mimeType||l},pause(){d.state==="recording"&&d.pause(),u&&u.state==="recording"&&u.pause()},resume(){d.state==="paused"&&d.resume(),u&&u.state==="paused"&&u.resume()},async stop(){clearInterval(T),b&&cancelAnimationFrame(b);let[g,w]=await Promise.all([O(d,m),O(u,v)]),_=d.mimeType||l||g[0]&&g[0].type||"video/webm",M=[...I].sort((me,$)=>me-$),A=M.length?M[Math.floor(M.length/2)]:null,S=L._meta(A),F=/webm|matroska/.test(_),z=async(me,$)=>{let Z=new Blob(me,{type:_});if(F&&Z.size)try{Z=new Blob([en(new Uint8Array(await Z.arrayBuffer()),Zi({...S,layout:$}))],{type:_})}catch(ti){L.log("record-tag-failed",{message:String(ti&&ti.message)})}return Z},k=await z(g,L.format),j={blob:k,type:_,layout:L.format,durationMs:Math.round(performance.now()-x),convergencePx:A,stereo:L.stereo,suggestedName:Ye(P,L.format,_),tagged:F&&k.size>0};return u&&(j.mono=await z(w,"mono"),j.monoSuggestedName=Ye(P,"mono",_)),L.log("record-stop",{bytes:k.size,mono:j.mono?j.mono.size:null,ms:j.durationMs,convergencePx:A,name:j.suggestedName}),j}}}close(){if(this.state!=="closed"){this.state="closed";for(let e of this.stream.getVideoTracks())e.removeEventListener?.("ended",this._onEnded);for(let e of[...this._views])e.remove();this.owned&&this.stream.getTracks().forEach(e=>e.stop()),this.video&&(this.video.srcObject=null),this.log("closed",{})}}};async function zt(n={}){let e=typeof n=="string"||n&&typeof n.getVideoTracks=="function"?{prefer:n}:n||{},t=e.prefer===void 0||e.prefer===null?"auto":e.prefer,i=typeof e.log=="function"?e.log:e.debug?(a,l)=>console.log(`${ee} ${a} ${JSON.stringify(l)}`):null,r=e.calibration&&typeof e.calibration=="object"?{...e.calibration}:{};r.horizontalFovDeg>0&&!(r.hfovDeg>0)&&(r.hfovDeg=r.horizontalFovDeg),delete r.horizontalFovDeg;let s=await Ni(t,{format:e.format,calibration:r,mediaDevices:e.mediaDevices,log:i||void 0});if(s.format==="sbs"&&typeof e.rectify=="function")try{let a=await e.rectify(s.stream,{width:s.width,height:s.height,deviceId:s.deviceId,label:s.label});a&&typeof a.getVideoTracks=="function"&&(s.stream=a,s.calibration={...s.calibration,rectified:!0})}catch(a){i?.("rectify-failed",{message:String(a&&a.message)}),s.rectifyError=a}let o=new Wt(s,{log:i});return s.rectifyError&&(o.rectifyError=s.rectifyError),o.log("open",{format:o.format,width:o.width,height:o.height,label:o.label,stereo:o.stereo,skipped:o.skipped.length}),o}var Ze=n=>!!n&&typeof n=="object"&&typeof n.capturePhoto=="function"&&typeof n.record=="function"&&n.stream&&typeof n.stream.getVideoTracks=="function";function Wr(n){let e=Math.min(globalThis.devicePixelRatio||1,2),t=Math.round((n.clientWidth||0)*e),i=Math.round((n.clientHeight||0)*e);return!t||!i?!1:((n.width!==t||n.height!==i)&&(n.width=t,n.height=i),!0)}function Ht(n,e,t,i={}){if(!e||typeof e.getContext!="function")throw new TypeError(`${ee} addCameraView(wall, canvas, cam, opts) needs a canvas`);if(!Ze(t))throw new TypeError(`${ee} addCameraView: cam must be a StereoCamera from openCamera()`);let r=new Nt(n,e,t,i);return t._views?.add(r),r}var Nt=class{constructor(e,t,i,r){this.wall=e||null,this.canvas=t,this.cam=i,this.mirror=r.mirror===void 0?!0:!!r.mirror,this.aspect=typeof r.aspect=="number"&&r.aspect>.3&&r.aspect<4?r.aspect:16/9,this.autoConverge=!!r.autoConverge,this.conv=xe(),this.conv.depth=0,this.setDepth(r.depth),this.route=null,this.handle=null,this.fallbackReason=null,this._fw=null,this._onRouteChange=typeof r.onRouteChange=="function"?r.onRouteChange:null,this._layerFails=0,this._layerTimer=0,this.buffer=null,this.removed=!1,this._raf=0,this._loop=r._loop!==!1,this._autoAt=0,this._track=qe(),this._focus=Ce(),this._scratch=null,this.disparityPx=null,this._reroute(!1),this._loop&&this._start()}get woven(){return this.route==="woven-sbs"}weaveState(){return{route:this.route,woven:this.woven,reason:this.fallbackReason,firstWoven:this.route==="woven-sbs"?this._fw?{...this._fw}:"pending":null,layerRetries:this._layerFails}}get convergencePx(){return this.conv.current}get depth(){return this.conv.depth}setDepth(e){let t=e==null||!Number.isFinite(+e)?0:Math.max(-1,Math.min(1,+e));return this.conv.depth=t,t}setMirror(e){return this.mirror=e===void 0?!this.mirror:!!e,this.mirror}setAutoConverge(e){return this.autoConverge=e===void 0?!this.autoConverge:!!e,this.autoConverge||(this._track.reset(),this._focus.reset(),this.conv.measuredPx=null,this.disparityPx=null),this.autoConverge}_reroute(e,t){if(t!==void 0&&(this.wall=t),this.removed)return;e&&this.fallbackReason&&(this.fallbackReason=null,clearTimeout(this._layerTimer),this._layerTimer=0);let i=this.cam,r=i.state==="live"&&i.video,o=i.format==="sbs"&&r&&this.wall&&this.wall.supported&&!this.fallbackReason?"woven-sbs":i.format==="sbs"?"flat-left":"flat";if(!e&&o===this.route)return;let a=this.route;this._unregister(),this.route=o,o==="woven-sbs"&&this._registerWoven(),o!==a&&this._routeChanged()}_registerWoven(){this.buffer||(this.buffer=document.createElement("canvas")),this._paintWoven();let e=this.wall.addImage(this.canvas,this.buffer);this.handle=e,this._fw=null;let t=e&&e.firstWoven;!t||typeof t.then!="function"||t.then(i=>{this.handle!==e||this.removed||!i||(this._fw={woven:!!i.woven,confirmed:!!i.confirmed,reason:i.reason||null,ms:i.ms},this.cam.log?.("view-first-woven",{woven:!!i.woven,reason:i.reason||null}),i.woven?(this._layerFails=0,this._routeChanged()):i.reason!=="removed"&&this._layerLost(i.reason||"layer-failed"))})}_layerLost(e){if(this.fallbackReason=e,this._reroute(!1),e!=="layer-failed"||this._layerFails>=Or)return;let t=Math.min(Pr,Ir*Math.pow(2,this._layerFails++));this.cam.log?.("view-layer-retry",{attempt:this._layerFails,inMs:t}),clearTimeout(this._layerTimer),this._layerTimer=setTimeout(()=>{this._layerTimer=0,!(this.removed||this.fallbackReason!==e)&&this._reroute(!0)},t)}_routeChanged(){if(this._onRouteChange)try{this._onRouteChange(this.route,this.weaveState())}catch(e){console.error(`${ee} onRouteChange threw`,e)}}_onWallLost(){this._reroute(!0,{supported:!1})}_unregister(){if(this.handle){try{this.handle.remove()}catch{}this.handle=null}}_start(){let e=()=>{this._raf=requestAnimationFrame(e),this.paint()};this._raf=requestAnimationFrame(e)}paint(){if(this.removed)return;let e=this.cam.video;!e||this.cam.state==="closed"||(this.route==="woven-sbs"?this._paintWoven():this._paintFlat(e))}_paintFlat(e){if(!Wr(this.canvas))return;let t=e.videoWidth,i=e.videoHeight;if(!t||!i||(e.readyState||0)<2)return;let r=this.canvas.getContext("2d"),s=this.route==="flat-left"?t/2:t,o=X(s,i,this.canvas.width/this.canvas.height,0,0);r.save(),this.mirror&&(r.translate(this.canvas.width,0),r.scale(-1,1)),r.drawImage(e,o.sx,o.sy,o.sw,o.sh,0,0,this.canvas.width,this.canvas.height),r.restore()}_paintWoven(){let e=this.cam.video,t=e.videoWidth,i=e.videoHeight;if(!t||!i||(e.readyState||0)<2||!this.buffer)return;let r=t/2,s=this.aspect,{w:o,h:a}=be(r,i,s),l=this.buffer;(l.width!==2*o||l.height!==a)&&(l.width=2*o,l.height=a),this.autoConverge&&this._sample(e);let c=this.conv.step(r),p=l.getContext("2d");if(this.mirror)for(let f of ae(t,i)){let h=f.src==="L"?0:1,d=X(r,i,s,c,h),m=f.dx===0?0:o;p.save(),p.translate(m+o,0),p.scale(-1,1),p.drawImage(e,f.sx+d.sx,d.sy,d.sw,d.sh,0,0,o,a),p.restore()}else for(let f of[0,1]){let h=X(r,i,s,c,f);p.drawImage(e,f*r+h.sx,h.sy,h.sw,h.sh,f*o,0,o,a)}}_sample(e){let t=performance.now();if(t-this._autoAt<Dr)return;this._autoAt=t,this._scratch=this._scratch||document.createElement("canvas");let i=an(e,this._scratch),r=i?this._focus.measure(i.img,i.w,i.h,t):null,s=this._track.push(r?r.d/i.scale:null);this.conv.measuredPx=s,this.disparityPx=s}remove(){this.removed||(this.removed=!0,this._raf&&cancelAnimationFrame(this._raf),this._raf=0,clearTimeout(this._layerTimer),this._layerTimer=0,this._unregister(),this.cam._views?.delete(this))}};var cn=[[-1,7,10,15,20,26,18,20,24,30,18],[-1,10,16,26,18,24,16,18,22,22,26]],dn=[[-1,1,1,1,1,1,2,2,2,2,4],[-1,1,1,1,2,2,4,4,4,5,5]],Nr=[1,0],Vt=10;function hn(n){let e=(16*n+128)*n+64;if(n>=2){let t=Math.floor(n/7)+2;e-=(25*t-10)*t-55,n>=7&&(e-=36)}return e}var ln=(n,e)=>Math.floor(hn(n)/8)-cn[e][n]*dn[e][n];function $t(n,e){let t=0;for(let i=7;i>=0;i--)t=t<<1^(t>>>7)*285,t^=(e>>>i&1)*n;return t}function zr(n){let e=new Array(n-1).fill(0);e.push(1);let t=1;for(let i=0;i<n;i++){for(let r=0;r<e.length;r++)e[r]=$t(e[r],t),r+1<e.length&&(e[r]^=e[r+1]);t=$t(t,2)}return e}function Hr(n,e){let t=e.map(()=>0);for(let i of n){let r=i^t.shift();t.push(0),e.forEach((s,o)=>t[o]^=$t(s,r))}return t}function Ut(n,e={}){let t=e.ecl==="L"?0:1,i=[...new TextEncoder().encode(String(n))],r=1;for(;r<=Vt&&!(4+(r<=9?8:16)+i.length*8<=ln(r,t)*8);r++);if(r>Vt)throw new Error(`qrEncode: ${i.length} bytes is too long for a version-${Vt} code`);let s=[],o=(g,w)=>{for(let _=w-1;_>=0;_--)s.push(g>>>_&1)};o(4,4),o(i.length,r<=9?8:16);for(let g of i)o(g,8);let a=ln(r,t)*8;o(0,Math.min(4,a-s.length)),o(0,(8-s.length%8)%8);for(let g=236;s.length<a;g^=253)o(g,8);let l=[];for(let g=0;g<s.length;g+=8)l.push(s.slice(g,g+8).reduce((w,_)=>w<<1|_,0));let c=dn[t][r],p=cn[t][r],f=Math.floor(hn(r)/8),h=c-f%c,d=Math.floor(f/c),m=zr(p),u=[];for(let g=0,w=0;g<c;g++){let _=l.slice(w,w+d-p+(g<h?0:1));w+=_.length;let M=Hr(_,m);g<h&&_.push(0),u.push(_.concat(M))}let v=[];for(let g=0;g<u[0].length;g++)for(let w=0;w<u.length;w++)(g!==d-p||w>=h)&&v.push(u[w][g]);let y=r*4+17,b=Array.from({length:y},()=>new Array(y).fill(!1)),C=Array.from({length:y},()=>new Array(y).fill(!1)),x=(g,w,_)=>{b[w][g]=_,C[w][g]=!0};for(let g=0;g<y;g++)x(6,g,g%2===0),x(g,6,g%2===0);let I=(g,w)=>{for(let _=-4;_<=4;_++)for(let M=-4;M<=4;M++){let A=Math.max(Math.abs(M),Math.abs(_)),S=g+M,F=w+_;S>=0&&S<y&&F>=0&&F<y&&x(S,F,A!==2&&A!==4)}};I(3,3),I(y-4,3),I(3,y-4);let T=[];if(r>1){let g=Math.floor(r/7)+2,w=Math.ceil((r*4+4)/(g*2-2))*2;T.push(6);for(let _=y-7;T.length<g;_-=w)T.splice(1,0,_)}for(let g=0;g<T.length;g++)for(let w=0;w<T.length;w++)if(!(g===0&&w===0||g===0&&w===T.length-1||g===T.length-1&&w===0))for(let _=-2;_<=2;_++)for(let M=-2;M<=2;M++)x(T[g]+M,T[w]+_,Math.max(Math.abs(M),Math.abs(_))!==1);let O=g=>{let w=Nr[t]<<3|g,_=w;for(let S=0;S<10;S++)_=_<<1^(_>>>9)*1335;let M=(w<<10|_)^21522,A=S=>(M>>>S&1)!==0;for(let S=0;S<=5;S++)x(8,S,A(S));x(8,7,A(6)),x(8,8,A(7)),x(7,8,A(8));for(let S=9;S<15;S++)x(14-S,8,A(S));for(let S=0;S<8;S++)x(y-1-S,8,A(S));for(let S=8;S<15;S++)x(8,y-15+S,A(S));x(8,y-8,!0)};if(O(0),r>=7){let g=r;for(let _=0;_<12;_++)g=g<<1^(g>>>11)*7973;let w=r<<12|g;for(let _=0;_<18;_++){let M=(w>>>_&1)!==0,A=y-11+_%3,S=Math.floor(_/3);x(A,S,M),x(S,A,M)}}let P=0;for(let g=y-1;g>=1;g-=2){g===6&&(g=5);for(let w=0;w<y;w++)for(let _=0;_<2;_++){let M=g-_,S=(g+1&2)===0?y-1-w:w;!C[S][M]&&P<v.length*8&&(b[S][M]=(v[P>>>3]>>>7-(P&7)&1)!==0,P++)}}let L=g=>{for(let w=0;w<y;w++)for(let _=0;_<y;_++){if(C[w][_])continue;let M;switch(g){case 0:M=(_+w)%2===0;break;case 1:M=w%2===0;break;case 2:M=_%3===0;break;case 3:M=(_+w)%3===0;break;case 4:M=(Math.floor(_/3)+Math.floor(w/2))%2===0;break;case 5:M=_*w%2+_*w%3===0;break;case 6:M=(_*w%2+_*w%3)%2===0;break;default:M=((_+w)%2+_*w%3)%2===0}M&&(b[w][_]=!b[w][_])}},R=Number.isInteger(e.mask)?e.mask:-1;if(R<0){let g=1/0;for(let w=0;w<8;w++){L(w),O(w);let _=Vr(b,y);_<g&&(g=_,R=w),L(w)}}return L(R),O(R),{version:r,size:y,mask:R,modules:b}}function Vr(n,e){let t=0,i=[];for(let o=0;o<e;o++)i.push(n[o]);for(let o=0;o<e;o++)i.push(n.map(a=>a[o]));for(let o of i){let a=1;for(let c=1;c<=e;c++)c<e&&o[c]===o[c-1]?a++:(a>=5&&(t+=a-2),a=1);let l=o.map(c=>c?"1":"0").join("");for(let c of["10111010000","00001011101"])for(let p=l.indexOf(c);p>=0;p=l.indexOf(c,p+1))t+=40}let r=0;for(let o=0;o<e;o++)for(let a=0;a<e;a++)if(n[o][a]&&r++,a<e-1&&o<e-1){let l=n[o][a];l===n[o][a+1]&&l===n[o+1][a]&&l===n[o+1][a+1]&&(t+=3)}let s=e*e;return t+=Math.floor(Math.abs(r*20-s*10)/s)*10,t}function fn(n,e,{px:t=4,dark:i="#000",light:r="#fff",ecl:s="M"}={}){let o=Ut(e,{ecl:s}),a=o.size+8;n.width=n.height=a*t;let l=n.getContext("2d");l.fillStyle=r,l.fillRect(0,0,a*t,a*t),l.fillStyle=i;for(let c=0;c<o.size;c++)for(let p=0;p<o.size;p++)o.modules[c][p]&&l.fillRect((p+4)*t,(c+4)*t,t,t);return o}function Y(n,e){let t=new Error(`@displayxr/inline3d/call: ${e}`);return t.code=n,t}async function Bt(n){let e=await globalThis.crypto.subtle.digest("SHA-256",new TextEncoder().encode(String(n)));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}var Qe="wss://signal.displayxr.org",un=Object.freeze([Qe,"wss://dxr-signal.displayxr.workers.dev"]),pn=["bad-room","bad-id","bad-version","bad-key","origin-not-allowed","blocked"];function fe(n=Qe,e={}){if(!n||typeof n!="string")throw Y("no-signaling-url","dxrSignaling(url): url must be a ws:// or wss:// string (omit it for the hosted DisplayXR server)");let t=c=>String(c).replace(/\/+$/,""),i=t(n),r=e.WebSocket||globalThis.WebSocket,s=e.pingMs||2e4,o=Array.isArray(e.aliases)?e.aliases.filter(c=>typeof c=="string"&&c).map(t):un.includes(i)?[...un]:[],a=[i,...o.filter(c=>c!==i)],l=0;return{name:"dxr",url:i,async join(c,p){let h=`k=${await Bt(c)}${typeof e.key=="string"&&e.key?`&key=${encodeURIComponent(e.key)}`:""}`,d=L=>`${a[L]}/v1/connect?${h}`,m=null,u=!1,v=0,y=null,b=new Set,C=[],x=L=>I(L,a.length),I=(L,R)=>new Promise((g,w)=>{let _=!1,M=!1,A=!1,S=new r(d(l));m=S;let F=z=>{if(!_){_=!0;try{S.close()}catch{}w(z)}};S.onopen=()=>{A=!0,S.send(JSON.stringify({t:"join",v:1,room:c,id:p.id,max:p.maxPeers}))},S.onmessage=z=>{let k;try{k=JSON.parse(typeof z.data=="string"?z.data:String(z.data))}catch{return}switch(k.t){case"welcome":{v=0;let j=Array.isArray(k.peers)?k.peers.filter($=>typeof $=="string"):[];clearInterval(y),y=setInterval(()=>T({t:"ping"}),s);let me=C;C=[];for(let $ of me)T($);if(L){let $=new Set(j);for(let Z of b)$.has(Z)||p.onPeerLeft?.(Z);b=$,p.onReconnect?.(j)}else b=new Set(j);_=!0,M=!0,g({id:k.id,peers:j,iceServers:Array.isArray(k.iceServers)?k.iceServers:void 0,max:k.max,tier:k.tier==="key"?"key":"anon",key:typeof k.key=="string"?k.key:void 0,turn:k.turn&&typeof k.turn=="object"?k.turn:void 0});break}case"full":u=!0,F(Y("room-full",`this call is full (${k.max} participants)`));break;case"expired":{u=!0,clearInterval(y);let j=Y("expired","this room has reached its lifetime on the signalling server");_?p.onDisconnect?.(j):F(j);break}case"error":if(!_&&pn.includes(k.code))u=!0,F(Y(k.code,k.message||k.code));else if(!_&&(k.code==="rate-limited"||k.code==="quota")){let j=Y(k.code,k.message||k.code);j.retryMs=k.retryMs>0?k.retryMs:0,F(j)}else!_&&k.code==="id-taken"&&F(Y("id-taken","peer id still held; retrying"));break;case"peer-joined":typeof k.id=="string"&&!b.has(k.id)&&(b.add(k.id),p.onPeerJoined?.(k.id));break;case"peer-left":typeof k.id=="string"&&(b.delete(k.id),p.onPeerLeft?.(k.id));break;case"signal":typeof k.from=="string"&&p.onSignal?.(k.from,k.data);break}},S.onerror=()=>{if(!A&&!_&&R>1){_=!0,l=(l+1)%a.length,I(L,R-1).then(g,w);return}F(Y("signaling-unreachable",`cannot reach ${a[l]}`))},S.onclose=()=>{clearInterval(y),F(Y("signaling-closed","signalling closed before joining")),M&&!u&&m===S&&O()}}),T=L=>{m&&m.readyState===1?m.send(JSON.stringify(L)):u||C.push(L)},O=()=>{p.onDisconnect?.();let L=()=>{u||x(!0).catch(R=>{if(u||R&&(R.code==="room-full"||pn.includes(R.code))){p.onDisconnect?.(R);return}setTimeout(L,Math.max(B(v++,{baseMs:500,maxMs:15e3}),R&&R.retryMs||0))})};setTimeout(L,B(v++,{baseMs:300,maxMs:15e3}))};return{...await x(!1),send:(L,R)=>T({t:"signal",to:L,data:R}),leave:()=>{if(!u){u=!0,clearInterval(y);try{m&&m.readyState===1&&m.send(JSON.stringify({t:"leave"})),m&&m.close(1e3,"leave")}catch{}}}}}}}var qt=Object.freeze({azure:"#4da3ff",violet:"#9b7bff",magenta:"#ff4fa3",sunset:"#ff7a45",amber:"#ffc23d",lime:"#9be15d",mint:"#35e0b0",ice:"#8fe3ff"}),gn=n=>typeof n=="string"&&qt[n.toLowerCase()]||n,_n=Object.freeze({accent:"--dxr-accent",ink:"--dxr-ink",shell:"--dxr-shell",danger:"--dxr-danger",radius:"--dxr-radius",font:"--dxr-font"}),De=Object.freeze({lobbyStartTitle:"Start a 3D call",lobbyJoinTitle:"Join the 3D call",lobbyFullTitle:"This call is full",lobbyLeftTitle:"You left the call",lobbyFullText:"It already has {maxPeers} participants.",lobbyText:"Check your framing below. Camera: {camera} \u2014 {kind}.",cameraDefault:"default",kindBusy:"busy (joining audio-only)",kindNone:"none (joining audio-only)",kindSbs:"sending 3D (side-by-side, {width}\xD7{height})",kindMono:"sending 2D ({width}\xD7{height})",liftOff:"Mono cameras: 2D (2D\u21923D is off).",liftChecking:"Mono cameras: checking 2D\u21923D\u2026",liftMissing:"Mono cameras: 2D\u21923D unavailable in this build.",liftNoProvider:"Mono cameras: 2D (no 2D\u21923D provider here).",liftNative:"Mono cameras: 2D\u21923D (native{provider}).",liftWeb:"Mono cameras: 2D\u21923D (in this page, WebGPU).",liftProven:"Mono cameras: 2D\u21923D.",liftUnproven:"Mono cameras: 2D\u21923D (confirmed on the first mono participant).",start:"Start 3D call",join:"Join call",rejoin:"Rejoin",retryCamera:"Retry camera",cameraSelect:"Camera",joining:"Joining\u2026",waitingTitle:"Waiting for others",waitingText:"Share this link (or scan the code). Anyone who opens it joins \u2014 keep it private.",inviteTitle:"Invite",inviteText:"Anyone with this link can join.",inviteLink:"Invite link",copyLink:"Copy link",copied:"Copied",pressCopy:"Press Ctrl/Cmd+C",qrLabel:"QR code of the invite link",banner2D:"You are seeing this call in 2D.",bannerLink:"View in 3D with DisplayXR Browser",mute:"Mute microphone",unmute:"Unmute microphone",cameraOn:"Turn camera on",cameraOff:"Turn camera off",cameraRetry:"No camera \u2014 click to retry",cameraBusyRetry:"{cameraBusy} \u2014 click to retry",depth:"Depth",invite:"Invite",leave:"Leave call",connecting:"Connecting\u2026",reconnecting:"Reconnecting\u2026",leftCall:"Left the call",cameraOffPlate:"Camera off",noCamera:"No camera",unreachable:"Can't reach this participant \u2014 the network needs a relay (TURN)",cameraBusy:"Camera busy \u2014 in use by another app (e.g. eye tracking)",you:"You",badge3D:"3D",badge2D3D:"2D\u21923D",badge2D:"2D",badgePending:"\u2026"});function vn(n){let e={...De,...n&&typeof n=="object"?n:{}};return(t,i)=>{let r=typeof e[t]=="string"?e[t]:De[t]||t;if(i)for(let[s,o]of Object.entries(i))r=r.split(`{${s}}`).join(String(o));return r}}var mn="dxr-call-style",Br=`
|
|
6
6
|
.dxr-call-host{--dxr-accent:#4da3ff;--dxr-ink:#fff;--dxr-shell:rgba(16,17,22,.92);--dxr-danger:#ff5a5f;--dxr-radius:12px;
|
|
7
7
|
--dxr-font:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
|
|
8
8
|
display:flex;flex-direction:column;gap:12px;color:var(--dxr-ink);
|
|
@@ -83,4 +83,4 @@ var _e=Object.freeze({speaker:"high",other:"normal",hidden:"paused"}),Cn=["high"
|
|
|
83
83
|
.dxr-call-depth{display:flex;align-items:center;gap:6px;padding:0 8px;font-size:12px;opacity:.9;}
|
|
84
84
|
.dxr-call-depth input{width:110px;accent-color:var(--dxr-accent);}
|
|
85
85
|
.dxr-call-note{font-size:12px;opacity:.65;}
|
|
86
|
-
`;function yn(n=document){if(n.getElementById(mn))return;let e=n.createElement("style");e.id=mn,e.textContent=Vr,(n.head||n.documentElement).appendChild(e)}var ee=n=>`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${n}"/></svg>`,q={mic:ee("M12 14a3 3 0 0 0 3-3V5a3 3 0 0 0-6 0v6a3 3 0 0 0 3 3zm5-3a5 5 0 0 1-10 0H5a7 7 0 0 0 6 6.92V21h2v-3.08A7 7 0 0 0 19 11z"),micOff:ee("M19 11h-2a5 5 0 0 1-.4 1.97l1.47 1.47A6.96 6.96 0 0 0 19 11zM15 11V5a3 3 0 0 0-5.94-.6L15 10.34zM4.27 3 3 4.27l6 6V11a3 3 0 0 0 4.52 2.59l1.46 1.46A5 5 0 0 1 7 11H5a7 7 0 0 0 6 6.92V21h2v-3.08a6.9 6.9 0 0 0 3.02-1.14L19.73 21 21 19.73z"),cam:ee("M17 10.5V7a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-3.5l4 4v-11z"),camOff:ee("M21 6.5l-4 4V7a1 1 0 0 0-1-1H9.82L21 17.18zM3.27 2 2 3.27 4.73 6H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h12c.21 0 .39-.08.54-.18L19.73 21 21 19.73z"),link:ee("M3.9 12a3.1 3.1 0 0 1 3.1-3.1h4V7H7a5 5 0 0 0 0 10h4v-1.9H7A3.1 3.1 0 0 1 3.9 12zM8 13h8v-2H8zm9-6h-4v1.9h4a3.1 3.1 0 0 1 0 6.2h-4V17h4a5 5 0 0 0 0-10z"),leave:ee("M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85a1 1 0 0 1-1.41-.02L.29 13.08a1 1 0 0 1 0-1.41C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67a1 1 0 0 1 0 1.41l-2.48 2.48a1 1 0 0 1-1.41.02 11.3 11.3 0 0 0-2.66-1.85 1 1 0 0 1-.56-.9v-3.1A15.3 15.3 0 0 0 12 9z"),mutedSmall:ee("M19 11h-2a5 5 0 0 1-.4 1.97l1.47 1.47A6.96 6.96 0 0 0 19 11zM15 11V5a3 3 0 0 0-5.94-.6L15 10.34zM4.27 3 3 4.27l6 6V11a3 3 0 0 0 4.52 2.59l1.46 1.46A5 5 0 0 1 7 11H5a7 7 0 0 0 6 6.92V21h2v-3.08a6.9 6.9 0 0 0 3.02-1.14L19.73 21 21 19.73z")};function E(n,e={},t=[]){let i=document.createElement(n);for(let[r,s]of Object.entries(e))s!=null&&(r==="class"?i.className=s:r==="html"?i.innerHTML=s:r==="text"?i.textContent=s:r.startsWith("on")&&typeof s=="function"?i.addEventListener(r.slice(2),s):r in i&&typeof s!="string"?i[r]=s:i.setAttribute(r,s));for(let r of[].concat(t))r&&i.appendChild(typeof r=="string"?document.createTextNode(r):r);return i}var W=(n,e)=>n&&n.classList.toggle("dxr-call-hidden",!e);var bn="[inline3d/call]",$r="https://github.com/DisplayXR/displayxr-browser",xn=Object.freeze({accent:"theme.accent",tileAspect:"theme.tileAspect",inviteBase:"invite.base",updateUrl:"invite.updateUrl",browserUrl:"landing.browserUrl",maxLifted:"liftOptions.max",calibration:"openCamera({ calibration }) of '@displayxr/inline3d/camera' (pass the camera as `camera`)",rectify:"openCamera({ rectify }) of '@displayxr/inline3d/camera'",log:"debug: true (and diagnostics())",recoverSession:"nothing \u2014 a call always recovers the document's session (sharedInline3D())",wallOptions:"sharedInline3D(opts) \u2014 the document's wall is configured by the page",scrollIntoView:"nothing \u2014 always on with ui: true"}),wn=new Set;function Ur(n){wn.has(n)||(wn.add(n),console.warn(`${bn} option \`${n}\` is deprecated (removed in 1.31) \u2014 use ${xn[n]}`))}function Xt(n={}){for(let v of Object.keys(xn))n[v]!==void 0&&Ur(v);let e=n.theme&&typeof n.theme=="object"?n.theme:{},t=n.invite&&typeof n.invite=="object"?n.invite:{},i=n.landing&&typeof n.landing=="object"?n.landing:{},r=n.ui===void 0?!0:n.ui==="tiles"?"tiles":!!n.ui,s=r===!0,o=e.tileAspect!==void 0?e.tileAspect:n.tileAspect,a=typeof o=="number"&&o>.3&&o<4?o:16/9,l=n.room===void 0||n.room===null?"auto":n.room;if(l!=="auto"&&!le(l)){let v=Se(l);if(!v)throw new Error(`@displayxr/inline3d/call: room "${l}" is not a valid room id (16-64 base64url chars) or invite link`);l=v}let c=n.liftOptions&&typeof n.liftOptions=="object"?{...n.liftOptions}:null,p=c&&c.max!==void 0?c.max:n.maxLifted;c&&delete c.max;let f=e.accent!==void 0?e.accent:n.accent,h={};for(let[v,y]of Object.entries(_n)){let b=v==="accent"?f:e[v];typeof b=="string"&&b?h[y]=v==="accent"?gn(b):b:typeof b=="number"&&v==="radius"&&(h[y]=`${b}px`)}let d=t.base!==void 0?t.base:n.inviteBase,m=t.updateUrl!==void 0?t.updateUrl:n.updateUrl,u=i.browserUrl!==void 0?i.browserUrl:n.browserUrl;return{room:l,signaling:n.signaling||fe(void 0,typeof n.key=="string"&&n.key?{key:n.key}:{}),iceServers:Array.isArray(n.iceServers)?n.iceServers:void 0,camera:n.camera===void 0?"auto":n.camera,format:n.format==="sbs"?"sbs":n.format==="mono"?"mono":void 0,calibration:n.calibration&&typeof n.calibration=="object"?{...n.calibration}:{},rectify:typeof n.rectify=="function"?n.rectify:null,audio:n.audio===void 0?!0:!!n.audio,autoConverge:n.autoConverge===void 0?!0:!!n.autoConverge,mono3D:ye(n.mono3D),maxPeers:Te(n.maxPeers===void 0?ae:n.maxPeers),liftOptions:c&&Object.keys(c).length?c:null,maxLifted:Number.isFinite(+p)&&p!==null&&p!==void 0?Math.max(0,Math.min(ae,Math.floor(+p))):ae,layout:n.layout==="speaker"?"speaker":n.layout==="none"?"none":"grid",ui:r,chrome:s,autoJoin:n.autoJoin===void 0?!s:!!n.autoJoin,selfView:n.selfView===void 0?!0:!!n.selfView,tileAspect:a,cssVars:h,strings:e.strings&&typeof e.strings=="object"?{...e.strings}:null,invite:{base:typeof d=="string"?d:null,updateUrl:m===void 0?s:!!m},landing:{browserUrl:typeof u=="string"?u:$r,allow2D:i.allow2D===void 0?!0:!!i.allow2D},debug:!!n.debug,log:typeof n.log=="function"?n.log:n.debug?(v,y)=>console.log(`${bn} ${v} ${JSON.stringify(y)}`):null,_liftImporter:typeof n._liftImporter=="function"?n._liftImporter:void 0}}var Vs=Object.freeze(["normalizeCallOptions","newRoomId","isValidRoomId","buildInviteLink","normalizeHello","makeHello","routeFor","badgeFor","createLiveGate","convergenceShiftPx","lowPass","clampShift","eyeCropRect","mirrorSwapOps","mirrorSwapPixels","maxBitrateKbps","measureFocusDisparity","preferVideoCodecs","sortCodecCapabilities","VIDEO_CODEC_ORDER","MeshTransport","clampMaxPeers","qrEncode","roomKey","SIGNAL_PROTOCOL","WIRE_VERSION","CALL_SDK","PLATE_TEXT","CALL_ACCENTS","normalizeMono3D","resolveLift","createLiftPool","createFrameWatch","liftConvergenceFor","liftPriorityFor","setLiftPriority","defaultLiftSpecifier","LIFT_PRIORITY"]);var Jt="dxr-call:",Br=["joined","left","peer","peerleft","state","display","speaker","quality","error","warning"],Gt="[inline3d/call] <dxr-call>",ue=n=>n!=null&&!/^(false|0|off|no)$/i.test(String(n).trim()),Sn=n=>{if(n==null||String(n).trim()==="")return;let e=/^\s*([0-9.]+)\s*\/\s*([0-9.]+)\s*$/.exec(String(n)),t=e?+e[1]/+e[2]:+n;return Number.isFinite(t)?t:void 0},N=n=>n==null||String(n).trim()===""?void 0:String(n).trim();function Kt(n){let e=typeof n=="function"?n:l=>n&&typeof n.getAttribute=="function"?n.getAttribute(l):null,t={},i=(l,c)=>{c!==void 0&&(t[l]=c)};i("room",N(e("room")));let r=N(e("signaling"));r&&(t.signaling=fe(r,N(e("key"))?{key:N(e("key"))}:{})),i("key",N(e("key"))),i("camera",N(e("camera"))),i("layout",N(e("layout"))),i("maxPeers",Sn(e("max-peers")));let s=N(e("ui"));ue(e("no-ui"))?t.ui=!1:s==="tiles"&&(t.ui="tiles"),ue(e("auto-join"))&&(t.autoJoin=!0);let o=N(e("mono3d"));o&&/^(off|false|0|no)$/i.test(o)&&(t.mono3D="off"),ue(e("no-audio"))&&(t.audio=!1),ue(e("no-self-view"))&&(t.selfView=!1),ue(e("no-auto-converge"))&&(t.autoConverge=!1);let a={accent:N(e("accent")),tileAspect:Sn(e("tile-aspect"))};return(a.accent!==void 0||a.tileAspect!==void 0)&&(t.theme=Object.fromEntries(Object.entries(a).filter(([,l])=>l!==void 0))),N(e("invite-base"))&&(t.invite={base:N(e("invite-base"))}),N(e("browser-url"))&&(t.landing={browserUrl:N(e("browser-url"))}),ue(e("debug"))&&(t.debug=!0),t}var qr=typeof HTMLElement=="function"?HTMLElement:class{},pe=class n extends qr{static mount=null;constructor(){super(),this.options=null,this.call=null,this.ready=null,this._gen=0,this._off=[],this._pending=null}connectedCallback(){if(this.call||this._pending)return;let e=++this._gen,t={...Kt(this),...this.options&&typeof this.options=="object"?this.options:{}},i=this.constructor.mount||n.mount||Yt;this._pending=new Promise(r=>r(i(this,t))).then(r=>{if(this._pending=null,e!==this._gen)return r.leave(),null;if(this.call=r,this._off=Br.map(s=>r.on(s,o=>this._dispatch(s,o))),this._off.push(r.on("error",s=>console.warn(`${Gt} ${s.code}: ${s.message}`))),this._dispatch("ready",{call:r}),r.state==="in-call"){this._dispatch("joined",{room:r.room,id:r.id});for(let s of r.peers)this._dispatch("peer",{id:s.id})}return r},r=>{throw this._pending=null,this._dispatch("error",{code:"mount-failed",message:String(r&&r.message||r),error:r||null}),console.warn(`${Gt} mount failed: ${String(r&&r.message||r)}`),r}),this.ready=this._pending,this.ready.catch(()=>{})}disconnectedCallback(){this._gen++;let e=this.call;this.call=null,e&&e.leave();for(let t of this._off)try{t()}catch{}this._off=[]}_dispatch(e,t){typeof CustomEvent!="function"||typeof this.dispatchEvent!="function"||this.dispatchEvent(new CustomEvent(Jt+e,{detail:t,bubbles:!0,composed:!0}))}};function et(n="dxr-call",e=globalThis.customElements){if(!e||typeof e.define!="function")return!1;let t=e.get(n);return t?(t!==pe&&console.warn(`${Gt} <${n}> is already defined by another class; leaving it`),!1):(e.define(n,pe),!0)}var G="[inline3d/call]",Xr=2e3,Gr=2500,Jr=500,Zt=.02,Kr=4,Yr=2,Zr=200,Mn=240,Qr=new Set(["I420","I420A","I422","I444","NV12"]);async function Tn(n,e,t={}){if(!e||typeof e.appendChild!="function")throw new TypeError("@displayxr/inline3d/call: addCall(wall, container, opts) needs a container element");let i=Xt(t);if(!i.signaling||typeof i.signaling.join!="function")throw new TypeError("@displayxr/inline3d/call: opts.signaling must be a SignalingAdapter \u2014 dxrSignaling([url]) or your own");let r=new Qt(n,e,i);return await r._init(),r.handle}async function Yt(n,e={}){if(!n||typeof n.appendChild!="function")throw new TypeError("@displayxr/inline3d/call: mountCall(el, opts) needs a container element");let{wall:t,...i}=e,r=t||await Fe(i.wallOptions);return Tn(r,n,i)}var Qt=class{constructor(e,t,i){this.o=i,this.t=vn(i.strings),this.container=t,this.wall=e||null,this.wallLive=!!(e&&e.supported),this.weaveLive=!1,this.camStatus="pending",this.id=Ai(),this.room=i.room==="auto"?Se(globalThis.location):i.room,this.state="idle",this.tiles=new Map,this.listeners=new Map,this.local=null,this.muted=!1,this.camOff=!1,this.depth=0,this.speakerId=null,this.transport=null,this._raf=0,this._statsTimer=0,this._hintGate=kt(bt),this.mono3D=i.mono3D,this.mono3DOn=i.mono3D!=="off",this.liftApi=null,this.liftPool=null,this._liftP=null,this.liftProven=!1,this.liftMissing=!1,this._liftWarned=!1,this._frameWatch=st(),this.handle=this._makeHandle(),this.wallLive&&this._hookWall(this.wall)}get woven(){return!!(this.wall&&this.wall.supported&&this.wallLive)}log(e,t={}){this.o.log&&this.o.log(e,t)}emit(e,t){let i=this.listeners.get(e);if(i)for(let r of[...i])try{r(t)}catch(s){console.error(`${G} '${e}' listener threw`,s)}}error(e,t,i){this.log("error",{code:e,message:t}),this.listeners.get("error")?.size||console.warn(`${G} ${e}: ${t}`),this.emit("error",{code:e,message:t,error:i||null})}warning(e,t){this.log("warning",{code:e,message:t}),console.warn(`${G} ${e}: ${t}`),this.emit("warning",{code:e,message:t})}async _init(){this._buildDom(),this.wallLive&&this._ensureLift(),await this._openMedia(this.o.camera),this._startLoop(),this.o.autoJoin?await this.join():this._setState("lobby")}async _openMedia(e,t,{keepOnFail:i=!1}={}){let r=(h,d)=>this.log(h,d),s=null,o=null,a=Ze(e)?e:null;try{if(s=a||await zt({prefer:e,format:t||this.o.format,calibration:this.o.calibration,rectify:this.o.rectify||void 0,log:r}),a&&a.state!=="live")throw Object.assign(new Error("the camera given is not live"),{code:"no-camera",skipped:[]})}catch(h){o=h;let d=h.code==="camera-busy";if(this.error(d?"camera-busy":h.code||"no-camera",d?`${this.t("cameraBusy")}. Joining audio-only.`:`no camera: ${h.message}. Joining audio-only.`,h),i&&this.local&&this.local.videoTrack)return this.local;this.camStatus=d?"busy":"none"}s&&(this.camStatus="ok"),s&&s.rectifyError&&this.error("rectify-failed",`rectify() threw \u2014 sending the raw pair: ${s.rectifyError.message}`,s.rectifyError);let l=this.local?this.local.audioTrack:null;this.o.audio&&!l&&(l=await zi({log:r})),l&&(l.enabled=!this.muted);let c=s&&s.stream.getVideoTracks()[0]||null;if(c){try{c.contentHint="detail"}catch{}c.enabled=!this.camOff}let p=new MediaStream([c,l].filter(Boolean)),f=this.local;return this.local={stream:p,cam:s,camStream:s?s.stream:null,video:s?s.video:null,videoTrack:c,audioTrack:l,format:s?s.format:"mono",width:s?s.width:0,height:s?s.height:0,calibration:s?s.calibration:{},owned:s?s.owned&&s!==a:!1,label:s?s.label:"",skipped:s?s.skipped:o?.skipped||[]},s&&s!==f?.cam&&(this._camEndedOff?.(),this._camEndedOff=s.on("ended",()=>{this.local?.cam===s&&(this.local.videoTrack=null,this.camStatus="none",this.error("no-camera",'the camera ended (revoked, unplugged, or taken by another app). Audio-only until "Retry camera".'),this.transport?.broadcast(this.stateMsg()),this._refreshSelf(),this._refreshBar())})),this.log("camera",{format:this.local.format,width:this.local.width,height:this.local.height,label:this.local.label,skipped:this.local.skipped.length}),f&&f.owned&&f.cam&&f.cam!==s&&f.cam.close(),this._refreshSelf(),this._refreshLobby(),this.local}hello(){let e=this.local||{};return Mt({format:e.format,width:e.width,height:e.height,baselineMm:e.calibration?.baselineMm,hfovDeg:e.calibration?.hfovDeg,rectified:!!e.calibration?.rectified})}stateMsg(){return{type:"state",muted:this.muted,cameraOff:this.camOff||!this.local?.videoTrack,speaking:!!this._selfSpeaking}}async join(){if(this.state==="joining"||this.state==="in-call")return this.handle;if(this.state==="left"&&!this.local?.videoTrack&&await this._openMedia(this.o.camera),this.room||(this.room=xt(),this.log("room-created",{})),this.o.invite.updateUrl&&globalThis.history&&globalThis.location)try{history.replaceState(history.state,"",He(location.href,this.room))}catch{}this._setState("joining");let e=new ke({signaling:this.o.signaling,id:this.id,maxPeers:this.o.maxPeers,iceServers:this.o.iceServers,log:(i,r)=>this.log(i,r)});this.transport=e;let t=null;try{t=await e.start({room:this.room,localStream:this.local.stream,sendFormat:this.local.format,onPeer:i=>this._onPeer(i),onPeerLeft:(i,r)=>this._onPeerLeft(i,r),onStream:(i,r)=>this.tiles.get(i)?.setStream(r),onMessage:(i,r)=>this._onMessage(i,r),onPeerState:(i,r)=>{this.tiles.get(i)?.setConn(r),this.emit("state",{id:i,state:r})},onRefused:i=>this.log("refused-peer",{id:i}),onGhost:(i,r)=>this._onGhost(i,r),onSignalingState:(i,r)=>{this.log("signaling",{state:i}),i==="closed"&&r&&this.error(r.code||"signaling-closed",r.message,r)}})}catch(i){throw this.transport=null,i&&i.code==="room-full"?(this._setState("full"),this.error("room-full",i.message,i)):(this._setState("lobby"),this.error(i.code||"join-failed",`could not join: ${i.message}`,i)),i}if(this._setState("in-call"),this.o.chrome)try{this.container.scrollIntoView?.({block:"start",behavior:"instant"}),this._fitGrid()}catch{}return this._startStats(),this._pagehide=()=>this.leave("pagehide"),globalThis.addEventListener?.("pagehide",this._pagehide),this.log("joined",{id:this.id,peers:this.tiles.size}),this.emit("joined",{room:this.room,id:this.id}),setTimeout(()=>{this.transport===e&&this._reportTurn(t)},0),this.handle}_reportTurn(e){let t=e&&e.turn;!t||typeof t!="object"||(t.status==="off"&&t.reason==="cap"?this.error("turn-cap","relay (TURN) capacity for this month is used up; direct connections still work, but a participant behind a strict NAT may be unreachable",null):(t.reason==="budget"||t.reason==="rate")&&this.warning("turn-shed",t.reason==="rate"?"no relay (TURN) for this session: too many credential requests from this address this hour":"no relay (TURN) for this anonymous session: the hosted service is near its monthly relay budget (a publishable key keeps TURN)"))}_onPeer(e){if(this.tiles.has(e))return;let t=new tt(this,e);this.tiles.set(e,t),this._layout(),this.emit("peer",{id:e})}_onGhost(e,t){let i=this.tiles.get(e);if(t&&!i){let r=new tt(this,e);r.ghost=!0,this.tiles.set(e,r),r.setConn("unreachable"),this._layout()}else!t&&i&&i.ghost&&(i.destroy(),this.tiles.delete(e),this._layout())}_onPeerLeft(e,t){let i=this.tiles.get(e);i&&(i.setConn("left"),this.emit("peerleft",{id:e,reason:t}),i.leaveTimer=setTimeout(()=>{i.destroy(),this.tiles.get(e)===i&&this.tiles.delete(e),this.speakerId===e&&this._setSpeaker(null),this._layout()},Gr))}_onMessage(e,t){let i=this.tiles.get(e);if(!i||!t)return;if(t.type==="__open"){this.transport.send(e,this.hello()),this.transport.send(e,this.stateMsg()),i.onChannelOpen();return}let r=St(t);if(r)return i.setHello(r);let s=Et(t);if(s)return i.setHint(s);let o=Oi(t);if(o)return i.setRemoteState(o)}inviteLink(){if(!this.room)return null;let e=this.o.invite.base||(globalThis.location?location.href:"");return He(e,this.room)}mute(e){return this.muted=e===void 0?!this.muted:!!e,this.local?.audioTrack&&(this.local.audioTrack.enabled=!this.muted),this.transport?.broadcast(this.stateMsg()),this._refreshBar(),this.log("mute",{muted:this.muted}),this.muted}setCameraOff(e){return this.camOff=e===void 0?!this.camOff:!!e,this.local?.videoTrack&&(this.local.videoTrack.enabled=!this.camOff),this.transport?.broadcast(this.stateMsg()),this._refreshBar(),this._refreshSelf(),this.camOff}setDepth(e){let t=e==null||!Number.isFinite(+e)?0:Math.max(-1,Math.min(1,+e));this.depth=t;for(let i of this.tiles.values())i.conv.depth=t;return this.liftPool?.setDepth(t),this.ui?.depth&&+this.ui.depth.value!==t&&(this.ui.depth.value=String(t)),t}async setCamera(e,{format:t}={}){let i=this.local?.format,r=await this._openMedia(e,t,{keepOnFail:!0});return this.transport&&(await this.transport.replaceTrack("video",r.videoTrack,r.stream),await this.transport.setSendFormat(r.format),this.transport.broadcast(this.hello()),this.transport.broadcast(this.stateMsg())),i!==r.format&&this.log("send-format",{format:r.format}),{format:r.format,width:r.width,height:r.height,label:r.label}}retryCamera(){return this.setCamera(this.o.camera,{format:this.o.format})}sendHint(e){if(!this._hintGate(performance.now()))return!1;let t=Et({type:"hint",subjectZmm:e});return t?(this.transport?.broadcast(t),!0):!1}leave(e="left"){if(this.state!=="left"){globalThis.removeEventListener?.("pagehide",this._pagehide),this.transport?.stop(),this.transport=null;for(let t of this.tiles.values())t.destroy();this.tiles.clear(),this.liftPool?.releaseAll(),clearInterval(this._statsTimer),this._setSpeaker(null),this.local&&(this._camEndedOff?.(),this._camEndedOff=null,this.local.stream.getTracks().forEach(t=>t.stop()),this.local.owned&&this.local.cam?this.local.cam.close():this.local.cam&&this.self?.detach(),this.local.videoTrack=null,this.local.audioTrack=null),this.self?.detach(),this._unhookWall(),this._setState("left"),this._layout(),this.emit("left",{room:this.room,reason:e})}}_hookWall(e){if(!e||!e.session||typeof e.session.addEventListener!="function")return;let t=e.close;this._wallHook={w:e,orig:t,pageClosed:!1};let i=this._wallHook;e.close=(...r)=>(i.pageClosed=!0,t.apply(e,r)),i.onEnd=()=>this._sessionEnded(i),e.session.addEventListener("end",i.onEnd),this._watchLive(e)}_watchLive(e){this.weaveLive=!1;let t=e.session;if(!t||typeof t.requestAnimationFrame!="function"){this.weaveLive=!0;return}let i=Rt(),r=performance.now(),s=(o,a)=>{if(e!==this.wall||!this.wallLive||this.state==="left")return;let l=null;if(e.refSpace)try{let c=a.getViewerPose(e.refSpace);l=c&&c.views?c.views.length:0}catch{l=0}if(!i.feed(l)){try{t.requestAnimationFrame(s)}catch{}return}this.weaveLive=!0,this.log("weave-live",{ms:Math.round(performance.now()-r)});for(let c of this.tiles.values())(c.route==="woven-sbs"||c.route==="lifted")&&c.reroute(!0);this.self&&this.self.route==="woven-sbs"&&this.self.reroute(!0),this._layout()};try{t.requestAnimationFrame(s)}catch{this.weaveLive=!0}}_unhookWall(){let e=this._wallHook;if(e){this._wallHook=null,e.w.close!==e.orig&&(e.w.close=e.orig);try{e.w.session.removeEventListener("end",e.onEnd)}catch{}}}_sessionEnded(e){if(this._wallHook===e){this.wallLive=!1,this.weaveLive=!1,this.log("session-ended",{byPage:e.pageClosed});for(let t of this.tiles.values())t.onWallLost();if(this.self?.onWallLost(),e.pageClosed||this.state==="left"){this._unhookWall();return}this.error("session-ended","the inline-3D session ended; tiles are flat while it is re-opened"),this._unhookWall(),this._recoverWall(0)}}_recoverWall(e){this.state==="left"||e>10||setTimeout(async()=>{if(this.state==="left")return;let t=null;try{t=await Fe()}catch{t=null}if(!t||!t.supported)return this._recoverWall(e+1);this.wall=t,this.wallLive=!0,this._hookWall(t),this.log("session-recovered",{attempt:e});for(let i of this.tiles.values())i.reroute(!0);this.self?.reroute(!0)},B(e,{baseMs:1e3,maxMs:15e3}))}_startLoop(){let e=0,t=i=>{this._raf=requestAnimationFrame(t);for(let r of this.tiles.values())r.paint();e&&this.liftPool&&this.liftPool.anyWeb&&this._watchFrames(i-e),e=i};this._raf=requestAnimationFrame(t)}_watchFrames(e){let t=this._frameWatch.feed(e);if(!t)return;let i={degraded:t==="degraded",frameMs:Math.round(this._frameWatch.frameMs*10)/10,tiles:this.liftPool.size};this.log("lift-frame-time",i),t==="degraded"&&console.warn(`${G} lifted tiles are slowing the page (~${Math.round(1e3/i.frameMs)} fps with ${i.tiles} lifted) \u2014 setMono3D(false) shows mono peers flat`),this.emit("quality",{id:null,in:null,out:null,lift:i})}_ensureLift(){if(!this.mono3DOn)return Promise.resolve(null);if(!this._liftP){let e=(r,s)=>this.log(r,s),t=this.o.liftOptions,i={webFallback:!0,...t&&t.models?{models:t.models}:{}};this._liftP=nt(this.mono3D,{log:e,capsOpts:i,...this.o._liftImporter?{importer:this.o._liftImporter}:{}}).then(r=>(this.liftApi=r,r.lift?(this.liftPool=ot({lift:r.lift,max:this.o.maxLifted,log:e,options:this.o.liftOptions}),this.liftPool.setDepth(this.depth),this.liftPool.setSpeaker(this.speakerId),!r.caps&&r.capabilities&&Promise.resolve().then(()=>r.capabilities(i)).then(s=>{r.caps=s||null,this._refreshLobby()}).catch(()=>{})):r.reason==="import-failed"||r.reason==="no-lift-export"?this.liftMissing=!0:r.reason!=="off"&&console.info(`${G} mono\u21923D unavailable (${r.reason}) \u2014 mono participants are shown flat`),this._rerouteMono(),this._refreshLobby(),r))}return this._liftP}_warnLiftMissing(){this._liftWarned||!this.liftMissing||!this.mono3DOn||(this._liftWarned=!0,this.warning("lift-not-bundled","a 2D participant is on a 3D display but the 2D\u21923D module could not be imported from this build, so they stay flat. Import it explicitly \u2014 `import { lift } from '@displayxr/inline3d/lift'; mountCall(el, { mono3D: lift })` \u2014 or use `@displayxr/inline3d/call/full`, which bundles it."))}_rerouteMono(){for(let e of this.tiles.values())e.format&&e.format!=="sbs"&&e.reroute(!1)}setMono3D(e){let t=e===void 0?!this.mono3DOn:!!e;return t===this.mono3DOn||(this.mono3DOn=t,t&&this.mono3D==="off"&&(this.mono3D="auto"),this._frameWatch.reset(),this.log("mono3d",{on:t}),this._rerouteMono(),t&&this.wallLive&&this._ensureLift(),this._refreshLobby()),t}_liftHint(){if(!this.wallLive)return"";let e=this.t;if(!this.mono3DOn)return e("liftOff");let t=this.liftApi;if(!t)return e("liftChecking");if(!t.lift)return this.liftMissing?e("liftMissing"):e("liftNoProvider");let i=t.caps;return i&&i.native?e("liftNative",{provider:i.provider?`, ${i.provider}`:""}):i&&i.webFallback&&i.webFallback.webgpu?e("liftWeb"):this.liftProven?e("liftProven"):e("liftUnproven")}_mono3DInfo(){let e=this.liftApi,t=e&&e.caps;return Object.freeze({on:this.mono3DOn,state:this.mono3DOn?e?e.lift?"ready":"unavailable":this._liftP?"loading":"idle":"off",reason:e?e.reason:null,native:t?!!t.native:null,provider:t&&t.provider||null,lifted:this.liftPool?this.liftPool.size:0,max:this.o.maxLifted,proven:this.liftProven})}_startStats(){clearInterval(this._statsTimer);let e=0;this._statsTimer=setInterval(()=>this._stats(++e%4===0),Jr)}async _stats(e){if(!this.transport)return;let t=null,i=0;for(let[o,a]of this.tiles){let l=this.transport.peerConnection(o);if(!l)continue;let c;try{c=await l.getStats()}catch{continue}let p={};c.forEach(d=>{d.type==="codec"&&(p[d.id]=d.mimeType)});let f={in:null,out:null};c.forEach(d=>{if(d.type==="inbound-rtp"&&d.kind==="audio"&&typeof d.audioLevel=="number"&&(a.level=Math.max(d.audioLevel,(a.level||0)*.6)),d.type==="media-source"&&d.kind==="audio"&&typeof d.audioLevel=="number"&&(i=Math.max(i,d.audioLevel)),!!e){if(d.type==="inbound-rtp"&&d.kind==="video"){let m=a._prevIn;f.in={width:d.frameWidth||0,height:d.frameHeight||0,fps:d.framesPerSecond||0,codec:p[d.codecId]||null,kbps:m?Math.round((d.bytesReceived-m.bytes)*8/(d.timestamp-m.t)):null,dropped:d.framesDropped||0,decoder:d.decoderImplementation||null},a._prevIn={bytes:d.bytesReceived,t:d.timestamp}}else if(d.type==="outbound-rtp"&&d.kind==="video"){let m=a._prevOut;f.out={width:d.frameWidth||0,height:d.frameHeight||0,fps:d.framesPerSecond||0,codec:p[d.codecId]||null,kbps:m?Math.round((d.bytesSent-m.bytes)*8/(d.timestamp-m.t)):null,limitation:d.qualityLimitationReason||null,encoder:d.encoderImplementation||null},a._prevOut={bytes:d.bytesSent,t:d.timestamp}}}}),e&&(f.in||f.out)&&(a.quality=f,this.emit("quality",{id:o,...f}));let h=a.remote.muted?0:a.level||0;a.setSpeaking(h>Zt||a.remote.speaking),h>Zt&&(!t||h>t.lvl)&&(t={id:o,lvl:h})}let r=t?t.id:null;r&&r!==this.speakerId?(this._challengeTicks=this._challenger===r?(this._challengeTicks||0)+1:1,this._challenger=r,this._challengeTicks>=2&&this._setSpeaker(r)):(this._challenger=null,this._challengeTicks=0);let s=!this.muted&&i>Zt;s!==!!this._selfSpeaking&&(this._selfSpeaking=s,this.transport?.broadcast(this.stateMsg()),this.self?.setSpeaking(s))}_setSpeaker(e){e!==this.speakerId&&(this.speakerId=e,this._challengeTicks=0,this.liftPool?.setSpeaker(e),this.emit("speaker",{id:e}),this.o.layout==="speaker"&&this._layout())}_fitGrid(){let e=this.ui;if(!e||!this.o.chrome||typeof globalThis.innerHeight!="number")return;let t=this.container.getBoundingClientRect?.(),i=e.grid.getBoundingClientRect?.();if(!t||!i||!i.height)return;let r=Math.max(160,Math.floor(globalThis.innerHeight-Math.max(0,t.top)-(t.height-i.height)-8)),s=parseFloat(this.container.style.getPropertyValue("--dxr-call-fit"))||0;Math.abs(r-s)>2&&this.container.style.setProperty("--dxr-call-fit",`${r}px`),this._fitHooked||(this._fitHooked=!0,globalThis.addEventListener?.("resize",()=>this._fitGrid()))}_setState(e){this.state=e,this.log("state",{state:e}),this._layout()}_buildDom(){let e=this.container,t=this.t;yn(e.ownerDocument||document),e.classList.add("dxr-call-host");for(let[r,s]of Object.entries(this.o.cssVars))e.style.setProperty(r,s);let i=this.ui={};i.banner=E("div",{class:"dxr-call-banner dxr-call-hidden",part:"banner"},[E("span",{text:t("banner2D")}),E("a",{href:this.o.landing.browserUrl,target:"_blank",rel:"noopener",text:t("bannerLink")})]),i.grid=E("div",{class:"dxr-call-grid",part:"grid","data-layout":this.o.layout,"data-n":"0"}),i.panel=E("div",{class:"dxr-call-panel dxr-call-hidden",part:"lobby"}),i.selfSlot=E("div",{class:"dxr-call-self",part:"self"}),i.bar=E("div",{class:"dxr-call-bar",part:"bar"}),i.foot=E("div",{class:"dxr-call-foot"},[i.selfSlot,i.bar]),i.invite=E("div",{class:"dxr-call-panel dxr-call-hidden",part:"invite"}),this.o.chrome||W(i.bar,!1),e.append(i.banner,i.panel,i.grid,i.invite,i.foot),this.o.selfView?this.self=new ei(this,i.selfSlot):W(i.selfSlot,!1),this.o.chrome&&this._buildBar()}_buildBar(){let e=this.ui,t=this.t,i=(r,s,o,a="")=>E("button",{class:`dxr-call-ib ${a}`,type:"button","aria-label":r,title:r,html:s,onclick:o});e.mic=i(t("mute"),q.mic,()=>this.mute()),e.cam=i(t("cameraOff"),q.cam,()=>this.local?.videoTrack?this.setCameraOff():this.retryCamera().catch(()=>{})),e.depth=E("input",{type:"range",min:"-1",max:"1",step:"0.05",value:"0","aria-label":t("depth")}),e.depth.addEventListener("input",()=>this.setDepth(+e.depth.value)),e.depth.addEventListener("dblclick",()=>this.setDepth(0)),e.inviteBtn=i(t("invite"),q.link,()=>{this._showInvite=!this._showInvite,this._layout()}),e.leave=i(t("leave"),q.leave,()=>this.leave(),"dxr-call-ib--leave"),e.bar.append(e.mic,e.cam,E("label",{class:"dxr-call-depth"},[t("depth"),e.depth]),e.inviteBtn,e.leave)}_refreshBar(){let e=this.ui;if(!e||!e.mic)return;let t=this.t;e.mic.innerHTML=this.muted?q.micOff:q.mic,e.mic.setAttribute("aria-pressed",String(this.muted)),e.mic.title=this.muted?t("unmute"):t("mute");let i=!this.local?.videoTrack;e.cam.innerHTML=this.camOff||i?q.camOff:q.cam,e.cam.setAttribute("aria-pressed",String(this.camOff||i)),e.cam.title=i?this.camStatus==="busy"?t("cameraBusyRetry",{cameraBusy:t("cameraBusy")}):t("cameraRetry"):this.camOff?t("cameraOn"):t("cameraOff")}_refreshSelf(){this.self?.update()}_refreshLobby(){(this.state==="lobby"||this.state==="idle")&&this._layout()}_renderInvite(e,t,i){e.replaceChildren();let r=this.inviteLink();if(!r)return;let s=this.t,o=E("input",{type:"text",readOnly:!0,value:r,"aria-label":s("inviteLink")});o.addEventListener("focus",()=>o.select());let a=E("button",{class:"dxr-call-btn dxr-call-btn--primary",type:"button",text:s("copyLink")});a.addEventListener("click",async()=>{try{await navigator.clipboard.writeText(r),a.textContent=s("copied")}catch{o.select(),a.textContent=s("pressCopy")}setTimeout(()=>a.textContent=s("copyLink"),1800)});let l=E("canvas",{"aria-label":s("qrLabel"),role:"img"});try{fn(l,r,{px:4})}catch{l.style.display="none"}e.append(E("h3",{text:t}),E("p",{text:i}),E("div",{class:"dxr-call-invite"},[E("div",{class:"dxr-call-row",style:"flex:1 1 280px"},[o,a]),l]))}_layout(){let e=this.ui;if(!e)return;let t=this.container,i=this.t,r=this.o.chrome&&(this.state==="lobby"||this.state==="idle"||this.state==="full"||this.state==="left");t.classList.toggle("dxr-call-host--lobby",r),W(e.banner,this.o.chrome&&!this.woven);let s=this.tiles.size;e.grid.dataset.n=String(Math.min(s,4)),W(e.grid,s>0&&this.state!=="left");let o=this.o.layout==="speaker"?this.speakerId||[...this.tiles.keys()][0]:null;for(let[c,p]of this.tiles)p.el.classList.toggle("dxr-call-tile--main",c===o);if(!this.o.chrome)return;this._refreshBar(),queueMicrotask(()=>this._fitGrid());let a=e.panel;if(r){W(a,!0),a.replaceChildren();let c=this.local,p=!!this.room,f=this.state==="full"?i("lobbyFullTitle"):this.state==="left"?i("lobbyLeftTitle"):i(p?"lobbyJoinTitle":"lobbyStartTitle"),h={width:c?.width||0,height:c?.height||0},d=this.camStatus==="busy"?i("kindBusy"):!c||!c.videoTrack?i("kindNone"):c.format==="sbs"?i("kindSbs",h):i("kindMono",h),m=this.state==="full"?i("lobbyFullText",{maxPeers:this.o.maxPeers}):`${i("lobbyText",{camera:c?.label||i("cameraDefault"),kind:d})}${this._liftHint()?` ${this._liftHint()}`:""}`,u=E("button",{class:"dxr-call-btn dxr-call-btn--primary",type:"button",text:this.state==="left"?i("rejoin"):i(p?"join":"start")});u.addEventListener("click",()=>this.join().catch(()=>{}));let v=E("select",{class:"dxr-call-select","aria-label":i("cameraSelect")});this._fillCameras(v),v.addEventListener("change",()=>this.setCamera(v.value).catch(b=>this.error("camera-failed",b.message,b)));let y=!c||!c.videoTrack?E("button",{class:"dxr-call-btn",type:"button",text:i("retryCamera")}):null;y?.addEventListener("click",()=>this.retryCamera().catch(()=>{})),a.append(E("h3",{text:f}),E("p",{text:m}),E("div",{class:"dxr-call-row"},[this.state==="full"?null:u,y,v]))}else this.state==="in-call"&&s===0?(W(a,!0),this._renderInvite(a,i("waitingTitle"),i("waitingText"))):this.state==="joining"?(W(a,!0),a.replaceChildren(E("p",{text:i("joining")}))):W(a,!1);let l=this.state==="in-call"&&s>0&&this._showInvite;l&&!e.invite.childElementCount&&this._renderInvite(e.invite,i("inviteTitle"),i("inviteText")),W(e.invite,l),l||e.invite.replaceChildren(),e.inviteBtn?.setAttribute("aria-pressed",String(!!l))}diagnostics(){let e=this.local;return{sdk:wt,wire:ze,state:this.state,wall:this.wall,wallLive:this.wallLive,weaveLive:this.weaveLive,woven:this.woven,local:e?{format:e.format,width:e.width,height:e.height,label:e.label,calibration:e.calibration,owned:e.owned,skipped:e.skipped,camera:e.cam||null,stream:e.stream}:null,hello:this.hello(),transport:this.transport,peers:[...this.tiles.values()].map(t=>t.diag()),mono3D:{...this._mono3DInfo(),lift:this.liftApi,pool:this.liftPool?this.liftPool.list():[]},speaker:this.speakerId,depth:this.depth,options:this.o,kill:t=>this.transport?._debugKill(t)}}async _fillCameras(e){let t=[];try{t=(await navigator.mediaDevices.enumerateDevices()).filter(r=>r.kind==="videoinput")}catch{}let i=this.local?.videoTrack?.getSettings?.().deviceId;e.replaceChildren(...t.map((r,s)=>E("option",{value:r.deviceId,text:r.label||`Camera ${s+1}`}))),i&&(e.value=i),W(e,t.length>1)}_makeHandle(){let e=this,t={format:"display",session:null},i={get room(){return e.room},get id(){return e.id},get state(){return e.state},get localFormat(){return e.local?e.local.format:null},get muted(){return e.muted},get cameraOff(){return e.camOff},get depth(){return e.depth},get speaker(){return e.speakerId},get camera(){return e.camStatus},get mono3D(){return e._mono3DInfo()},get peers(){return Object.freeze([...e.tiles.values()].map(s=>s.info()))},join:()=>e.join().then(()=>{}),inviteLink:()=>e.inviteLink(),mute:s=>e.mute(s),setCameraOff:s=>e.setCameraOff(s),setCamera:(s,o)=>e.setCamera(s,o),setDepth:s=>e.setDepth(s),retryCamera:()=>e.retryCamera(),setMono3D:s=>e.setMono3D(s),leave:()=>e.leave("left"),tile:s=>e.tiles.get(s)?.el||null,diagnostics:()=>e.diagnostics(),on(s,o){if(typeof o!="function")throw new TypeError(`${G} on() takes a function`);if(s in t&&!e._eventWarned?.has(s)){(e._eventWarned||=new Set).add(s);let a=t[s];console.warn(`${G} the '${s}' event is deprecated (removed in 1.31)${a?` \u2014 listen for '${a}'`:" \u2014 it is internal now; diagnostics() has the wall"}`)}return e.listeners.has(s)||e.listeners.set(s,new Set),e.listeners.get(s).add(o),()=>e.listeners.get(s)?.delete(o)},off(s,o){e.listeners.get(s)?.delete(o)}},r={wall:["diagnostics().wall (or the wall you passed / sharedInline3D())",()=>e.wall],format:["localFormat",()=>i.localFormat],sendHint:["nothing \u2014 auto-convergence superseded it",()=>s=>e.sendHint(s)],_debug:["diagnostics()",()=>({transport:e.transport,kill:s=>e.transport?._debugKill(s)})]};for(let[s,[o,a]]of Object.entries(r))Object.defineProperty(i,s,{enumerable:!1,configurable:!0,get(){return e._handleWarned?.has(s)||((e._handleWarned||=new Set).add(s),console.warn(`${G} handle.${s} is deprecated (removed in 1.31) \u2014 use ${o}`)),a()}});return i}};function es(n){let e=Math.min(globalThis.devicePixelRatio||1,2),t=Math.round((n.clientWidth||0)*e),i=Math.round((n.clientHeight||0)*e);return!t||!i?!1:((n.width!==t||n.height!==i)&&(n.width=t,n.height=i),!0)}function En(n,e,{eyeHalf:t=null,mirror:i=!1}={}){if(!es(n))return;let r=n.getContext("2d"),s=e.videoWidth,o=e.videoHeight;if(!s||!o||(e.readyState||0)<2)return;let a=t===null?s:s/2,l=X(a,o,n.width/n.height,0,0);r.save(),i&&(r.translate(n.width,0),r.scale(-1,1)),r.drawImage(e,(t||0)*a+l.sx,l.sy,l.sw,l.sh,0,0,n.width,n.height),r.restore()}var tt=class{constructor(e,t){this.call=e,this.id=t,this.hello=null,this.format=null,this.route=null,this.routedKey=null,this.handle=null,this.conn="connecting",this.remote={muted:!1,cameraOff:!1,speaking:!1},this.level=0,this.speaking=!1,this.quality=null,this.conv=xe(),this.autoTrack=qe(),this.autoFocus=Ce(),this.autoAt=0,this.autoCanvas=null,this.autoLocked=!1,this.autoStats={n:0,ms:0,readMs:0,method:null,via:null},this.autoPending=!1,this.autoGen=0,this.destroyed=!1,this.conv.depth=e.depth,this.hintGate=kt(bt),this.layerFails=0,this.forceFlat=!1,this.lifted=!1,this.liftHandle=null,this.liftLive=!1,this.liftFailed=!1,this.liftFails=0,this.visible=!0,this.video=Object.assign(document.createElement("video"),{muted:!0,playsInline:!0,autoplay:!0}),this.audio=Object.assign(document.createElement("audio"),{autoplay:!0}),this.video.addEventListener("playing",()=>this._maybeRoute()),this.video.addEventListener("loadeddata",()=>this._maybeRoute()),this.video.addEventListener("resize",()=>this._maybeRoute()),this.canvas=E("canvas"),this.cover=E("div",{class:"dxr-call-cover dxr-call-hidden"}),this.badge=E("div",{class:"dxr-call-badge",part:"badge"}),this.plate=E("div",{class:"dxr-call-state",part:"plate",text:e.t("connecting")}),this.stage=E("div",{class:"dxr-call-stage"},[this.canvas,this.cover,this.badge,this.plate]),this.stage.style.aspectRatio=String(e.o.tileAspect),this.el=E("div",{class:"dxr-call-tile",part:"tile","data-dxr-peer":t,"data-peer":t},[this.stage,E("div",{class:"dxr-call-talk"})]),e.o.ui||W(this.badge,!1),e.ui.grid.appendChild(this.el),this._renderBadge()}display(){return Ct(this.route)}info(){return Object.freeze({id:this.id,format:this.format||"mono",display:this.display(),state:this.conn,muted:this.remote.muted,cameraOff:this.remote.cameraOff,speaking:this.speaking})}diag(){return{...this.info(),route:this.route,rectified:!!(this.hello&&this.hello.rectified),hello:this.hello,quality:this.quality,convergencePx:this.conv.current,autoConverge:{disparityPx:this.conv.measuredPx,ms:this.autoStats.n?this.autoStats.ms/this.autoStats.n:null,readMs:this.autoStats.n?this.autoStats.readMs/this.autoStats.n:null,method:this.autoStats.method,via:this.autoStats.via},lift:this.lifted?{live:this.liftLive,native:!!(this.liftHandle&&this.liftHandle.native),priority:this.call.liftPool?this.call.liftPool.priority(this.id):null,state:this.liftHandle?this.liftHandle.state||null:"pending"}:null,element:this.el}}setStream(e){this.video.srcObject!==e&&(this.video.srcObject=e,this.audio.srcObject=e,this._resetAutoConverge()),this.video.play().catch(()=>{}),this.audio.play().catch(()=>{})}onChannelOpen(){clearTimeout(this.helloTimer),this.helloTimer=setTimeout(()=>{this.format||(this.format="mono",this._maybeRoute())},Xr)}setHello(e){clearTimeout(this.helloTimer),this.hello=e,this.conv.hello=e;let t=this.format!==e.format;this.format=e.format,this.call.log("hello",{peer:this.id,format:e.format,width:e.width,height:e.height,rectified:e.rectified}),t?this._maybeRoute():this._renderBadge()}setHint(e){this.hintGate(performance.now())&&(this.conv.subjectZmm=e.subjectZmm)}setRemoteState(e){this.remote=e,this._renderBadge(),this._renderPlate(),this._updateVisible()}setSpeaking(e){e!==this.speaking&&(this.speaking=e,this.el.classList.toggle("dxr-call-tile--speaking",e))}setConn(e){e==="unreachable"&&this.conn!=="unreachable"&&this.call.error("unreachable",`${this.call.t("unreachable")}. Still retrying in the background.`,Object.assign(new Error("unreachable"),{peer:this.id})),this.conn=e,e==="connected"&&this.leaveTimer&&(clearTimeout(this.leaveTimer),this.leaveTimer=null),this._renderPlate()}_renderPlate(){let e=this.call.t,t=this.conn==="left"?e("leftCall"):this.conn==="unreachable"?e("unreachable"):this.conn==="reconnecting"?e("reconnecting"):this.conn!=="connected"?e("connecting"):this.remote.cameraOff?e("cameraOffPlate"):null;this.plate.textContent=t||"",W(this.plate,!!t)}_renderBadge(){let e=this.call.t,t=this.route==="woven-sbs"?e("badge3D"):this.route==="lifted"?e("badge2D3D"):e("badge2D"),i=this.route?this.route==="lifted"&&!this.liftLive?`${t}${e("badgePending")}`:t:e("badgePending");this.badge.replaceChildren(E("b",{text:i})),this.badge.dataset.route=this.route||"",this.remote.muted&&this.badge.insertAdjacentHTML("beforeend",q.mutedSmall)}_maybeRoute(){!this.format||(this.video.readyState||0)<2||!this.video.videoWidth||this.reroute(!1)}reroute(e){let t=this.call,i=t.liftPool,r=this.forceFlat&&this.format==="sbs"?{route:"flat-left"}:Tt({format:this.format,woven:t.woven,mono3D:t.mono3DOn?"auto":"off",lift:!!i,overBudget:i?!i.canAcquire(this.id):!1,failed:this.liftFailed});this.format!=="sbs"&&t.woven&&t.mono3DOn&&!t._liftP&&t._ensureLift(),this.format!=="sbs"&&t.woven&&t.liftMissing&&t._warnLiftMissing();let s=`${r.route}|${this.format}`;!e&&s===this.routedKey||(this.routedKey=s,this._unregister(),this.route=r.route,r.route==="woven-sbs"?this._registerWoven():r.route==="lifted"&&this._registerLifted(),t.log("route",{peer:this.id,route:r.route,format:this.format,mono3d:r.mono3d||null}),t.emit("display",{id:this.id,display:this.display()}),t.listeners.get("format")?.size&&t.emit("format",{id:this.id,format:this.format,route:r.route,mono3d:r.mono3d||null,hello:this.hello}),this._renderBadge())}_registerWoven(){let e=this.call;this.convCanvas||(this.convCanvas=document.createElement("canvas")),this._paintConv(),W(this.cover,!0);let t=e.wall.addImage(this.canvas,this.convCanvas);this.handle=t,t.firstWoven?.then(i=>{this.handle===t&&(W(this.cover,!1),e.log("first-woven",{peer:this.id,woven:i.woven,reason:i.reason,ms:Math.round(i.ms)}),!i.woven&&i.reason==="layer-failed"&&this._layerFailed())})}_registerLifted(){let e=this.call,t=e.liftPool;this.lifted=!0,this.liftLive=!1,this.video.classList.add("dxr-call-liftsrc"),this.canvas.classList.add("dxr-call-liftflat"),this.video.parentNode!==this.stage&&this.stage.insertBefore(this.video,this.stage.firstChild),this._observeVisible(),t.acquire(this.id,this.video,{wall:e.wall,visible:this.visible,onError:i=>this._liftError(i)}).then(i=>{if(!i||!this.lifted||t.handle(this.id)!==i)return;this.liftHandle=i;let r=s=>{s==="live"?this._liftShowing(!0):(s==="error"||s==="disposed")&&this._liftShowing(!1)};this._liftOff=[i.on?.("statechange",s=>r(s&&s.state)),i.on?.("error",s=>{s&&s.fatal&&this._liftError(s.error)})],i.state==="live"?this._liftShowing(!0):i.canvas&&i.canvas.style&&(i.canvas.style.visibility="hidden"),e.log("lifted",{peer:this.id,native:!!i.native,woven:!!i.woven,state:i.state||null,provider:i.stats&&i.stats.provider||null})})}_liftShowing(e){if(e===this.liftLive)return;this.liftLive=e;let t=this.liftHandle;e?(t&&t.canvas&&t.canvas.style&&!t.native&&(t.canvas.style.visibility=""),this.canvas.style.visibility="hidden",this.liftFails=0,this.call.liftProven||(this.call.liftProven=!0,this.call._refreshLobby())):this.canvas.style.visibility="",this.call.log("lift-live",{peer:this.id,live:e}),this._renderBadge()}_liftError(e){this.lifted&&(this.call.log("lift-error",{peer:this.id,message:String(e&&e.message||e).slice(0,200)}),this.liftFailed=!0,this.reroute(!0),!(this.liftFails++>=Yr)&&(clearTimeout(this.liftTimer),this.liftTimer=setTimeout(()=>{this.liftFailed=!1,this.reroute(!1)},B(this.liftFails-1,{baseMs:3e3,maxMs:3e4}))))}_observeVisible(){this._io||typeof IntersectionObserver!="function"||(this._io=new IntersectionObserver(e=>{let t=e[e.length-1];this._onscreen=!!(t&&t.isIntersecting),this._updateVisible()}),this._io.observe(this.stage))}_updateVisible(){let e=this._onscreen!==!1&&!this.remote.cameraOff;e!==this.visible&&(this.visible=e,this.call.liftPool?.setVisible(this.id,e))}_layerFailed(){if(this.forceFlat=!0,this.reroute(!0),this.layerFails++>=Kr)return;let e=B(this.layerFails-1,{baseMs:1500,maxMs:2e4});this.call.log("layer-retry",{peer:this.id,attempt:this.layerFails,inMs:e}),clearTimeout(this.layerTimer),this.layerTimer=setTimeout(()=>{this.forceFlat=!1,this.call.woven&&this.reroute(!0)},e)}onWallLost(){this.handle=null,this.reroute(!0)}_unregister(){if(W(this.cover,!1),this.lifted){this.lifted=!1;for(let e of this._liftOff||[])typeof e=="function"&&e();this._liftOff=null,this.call.liftPool?.release(this.id),queueMicrotask(()=>this.call.state!=="left"&&this.call._rerouteMono()),this.liftHandle=null,this.liftLive=!1,this.canvas.style.visibility="",this.canvas.classList.remove("dxr-call-liftflat"),this._io&&(this._io.disconnect(),this._io=null),this.video.parentNode&&(this.video.remove(),this.video.classList.remove("dxr-call-liftsrc"),setTimeout(()=>this.video.srcObject&&this.video.play().catch(()=>{}),0))}if(this.handle){try{this.handle.remove()}catch{}this.handle=null}}paint(){this.route&&(this.route==="woven-sbs"?this._paintConv():this.route==="lifted"?this.liftLive||En(this.canvas,this.video):En(this.canvas,this.video,{eyeHalf:this.route==="flat-left"?0:null}))}_paintConv(){let e=this.video,t=e.videoWidth,i=e.videoHeight;if(!t||!i||(e.readyState||0)<2||!this.convCanvas)return;let r=t/2,s=this.call.o.tileAspect,{w:o,h:a}=be(r,i,s),l=this.convCanvas;(l.width!==2*o||l.height!==a)&&(l.width=2*o,l.height=a),this.call.o.autoConverge&&this._sampleDisparity(e,t,i);let c=this.conv.step(r),p=l.getContext("2d");for(let f of[0,1]){let h=X(r,i,s,c,f);p.drawImage(e,f*r+h.sx,h.sy,h.sw,h.sh,f*o,0,o,a)}}_sampleDisparity(e,t,i){let r=performance.now();if(this.autoPending||r-this.autoAt<Zr)return;if(this.autoAt=r,typeof VideoFrame=="function"){let f=null;try{f=new VideoFrame(e)}catch{f=null}if(f&&Qr.has(f.format)){this.autoPending=!0;let h=this.autoGen,d=f.visibleRect?f.visibleRect.width:f.displayWidth,m=f.visibleRect?f.visibleRect.height:f.displayHeight,u=new Uint8Array(f.allocationSize());f.copyTo(u).then(v=>{if(h!==this.autoGen)return;let y=performance.now(),b=Math.max(1,Math.ceil(d/2/Mn)),C=Vi(u,v[0].offset,v[0].stride,d,m,b);this._applyMeasurement(C.img,C.w,C.h,C.w/d,r,performance.now()-y,"videoframe")}).catch(()=>{h===this.autoGen&&this._applyMeasurement(null,0,0,1,r,0,"videoframe")}).finally(()=>{f.close(),this.autoPending=!1});return}f&&f.close()}let s=Math.min(1,Mn/(t/2)),o=Math.max(2,Math.round(t*s/2)*2),a=Math.max(2,Math.round(i*s));this.autoCanvas||(this.autoCanvas=document.createElement("canvas"));let l=this.autoCanvas;(l.width!==o||l.height!==a)&&(l.width=o,l.height=a);let c=l.getContext("2d",{willReadFrequently:!0}),p=null;try{c.drawImage(e,0,0,o,a),p=Be(c.getImageData(0,0,o,a).data,o*a)}catch{p=null}this._applyMeasurement(p,o,a,o/t,r,performance.now()-r,"canvas")}_applyMeasurement(e,t,i,r,s,o,a){if(this.destroyed)return;let l=performance.now(),c=e?this.autoFocus.measure(e,t,i,s):null,p=this.autoTrack.push(c?c.d/r:null);this.conv.measuredPx=p,this.autoStats.n++,this.autoStats.readMs+=o,this.autoStats.ms+=o+(performance.now()-l),this.autoStats.method=c?c.method:null,this.autoStats.via=a,c&&!this.autoLocked&&(this.autoLocked=!0,this.call.log("auto-converge",{peer:this.id,disparityPx:Math.round(p*10)/10,at:{x:Math.round(c.x/r),y:Math.round(c.y/r)},ncc:Math.round(c.c*100)/100,method:c.method,via:a,ms:Math.round(o+(performance.now()-l))}))}_resetAutoConverge(){this.autoGen++,this.autoTrack.reset(),this.autoFocus.reset(),this.conv.measuredPx=null,this.autoLocked=!1}destroy(){this.destroyed=!0,this.autoGen++,clearTimeout(this.helloTimer),clearTimeout(this.layerTimer),clearTimeout(this.leaveTimer),clearTimeout(this.liftTimer),this._unregister(),this.video.srcObject=null,this.audio.srcObject=null,this.el.remove()}},ei=class{constructor(e,t){this.call=e,this.canvas=E("canvas"),this.badge=E("div",{class:"dxr-call-badge",part:"badge"}),this.plate=E("div",{class:"dxr-call-state dxr-call-hidden",part:"plate"}),this.stage=E("div",{class:"dxr-call-stage"},[this.canvas,this.badge,this.plate]),this.stage.style.aspectRatio=String(e.o.tileAspect),this.el=E("div",{class:"dxr-call-tile dxr-call-tile--self",part:"tile"},[this.stage,E("div",{class:"dxr-call-talk"})]),t.appendChild(this.el),this.view=null,this.cam=null}get route(){return this.view?this.view.route:null}update(){let e=this.call.local,t=this.call.t,i=!e||!e.videoTrack;this.plate.textContent=i?this.call.camStatus==="busy"?t("cameraBusy"):this.call.camStatus==="pending"?"":t("noCamera"):this.call.camOff?t("cameraOffPlate"):"",W(this.plate,i||this.call.camOff),this.reroute(!1)}reroute(e){let t=this.call.local,i=t&&t.videoTrack?t.cam:null,r=this.call.woven?this.call.wall:{supported:!1};if(!i||i.state!=="live")return this.detach(),this._badge();this.view&&this.cam===i?this.view._reroute(e,r):(this.detach(),this.cam=i,this.view=Ht(r,this.canvas,i,{mirror:!0,autoConverge:!1,aspect:this.call.o.tileAspect})),this._badge()}_badge(){let e=this.call.t;this.badge.replaceChildren(E("b",{text:`${e("you")} \xB7 ${this.route==="woven-sbs"?e("badge3D"):e("badge2D")}`}))}onWallLost(){this.view?._onWallLost(),this._badge()}detach(){this.view&&this.view.remove(),this.view=null,this.cam=null}setSpeaking(e){this.el.classList.toggle("dxr-call-tile--speaking",e)}},ts="1.31",kn=new Set;function D(n,e,t){let i=()=>{kn.has(n)||(kn.add(n),console.warn(`${G} \`${n}\` is internal and leaves '@displayxr/inline3d/call' in ${ts} \u2014 import it from ${e} if you must, or stop depending on it`))};return typeof t=="function"?new Proxy(t,{apply(r,s,o){return i(),Reflect.apply(r,s,o)},construct(r,s){return i(),Reflect.construct(r,s)}}):t&&typeof t=="object"?new Proxy(t,{get(r,s,o){return typeof s=="string"&&i(),Reflect.get(r,s,o)}}):t}var oo=D("normalizeCallOptions","js/call/options.js",Xt),ao=D("newRoomId","js/call/wire.js",xt),lo=D("isValidRoomId","js/call/wire.js",le),co=D("buildInviteLink","js/call/wire.js",He),ho=D("normalizeHello","js/call/wire.js",St),fo=D("makeHello","js/call/wire.js",Mt),uo=D("routeFor","js/call/wire.js",Tt),po=D("badgeFor","js/call/wire.js",Ct),mo=D("createLiveGate","js/call/wire.js",Rt),go=D("convergenceShiftPx","js/camera/converge.js",je),_o=D("lowPass","js/camera/converge.js",Ne),vo=D("clampShift","js/camera/converge.js",We),yo=D("eyeCropRect","js/camera/geometry.js",X),wo=D("mirrorSwapOps","js/camera/geometry.js",oe),bo=D("mirrorSwapPixels","js/camera/geometry.js",yt),xo=D("maxBitrateKbps","js/call/wire.js",Ve),So=D("measureFocusDisparity","js/camera/disparity.js",It),Mo=D("preferVideoCodecs","js/call/sdp.js",Ee),Eo=D("sortCodecCapabilities","js/call/sdp.js",$e),ko=D("VIDEO_CODEC_ORDER","js/call/sdp.js",Me),To=D("MeshTransport","js/call/transport.js",ke),Co=D("clampMaxPeers","js/call/transport.js",Te),Ro=D("qrEncode","js/call/qr.js",Ut),Do=D("roomKey","js/call/signaling.js",Bt);var Lo=D("PLATE_TEXT","js/call/ui.js (CALL_STRINGS)",Object.freeze({unreachable:De.unreachable,cameraBusy:De.cameraBusy})),Ao=D("CALL_ACCENTS","js/call/ui.js",qt),Io=D("normalizeMono3D","js/call/lift.js",ye),Oo=D("resolveLift","js/call/lift.js",nt),Po=D("createLiftPool","js/call/lift.js",ot),Fo=D("createFrameWatch","js/call/lift.js",st),jo=D("liftConvergenceFor","js/call/lift.js",ve),Wo=D("liftPriorityFor","js/call/lift.js",Le),No=D("setLiftPriority","js/call/lift.js",rt),zo=D("defaultLiftSpecifier","js/call/lift.js",it),Ho=D("LIFT_PRIORITY","js/call/lift.js",_e);et();ii(()=>new URL("./lift.js",import.meta.url).href);export{Jt as CALL_EVENT_PREFIX,on as CAMERA_SDK,Qe as DXR_SIGNAL_DEFAULT,pe as DxrCallElement,Tn as addCall,Ht as addCameraView,Kt as attrsToOpts,Ti as createInline3D,et as defineCallElement,fe as dxrSignaling,Ei as inline3DAvailable,Ze as isStereoCamera,Yt as mountCall,zt as openCamera,Se as parseInviteLink,Pt as parseStereoXmp,Ji as readJpegStereoMeta,Ft as readJpegXmp,nn as readWebmStereoMeta,Fe as sharedInline3D,Ye as suggestedName};
|
|
86
|
+
`;function yn(n=document){if(n.getElementById(mn))return;let e=n.createElement("style");e.id=mn,e.textContent=Br,(n.head||n.documentElement).appendChild(e)}var te=n=>`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${n}"/></svg>`,q={mic:te("M12 14a3 3 0 0 0 3-3V5a3 3 0 0 0-6 0v6a3 3 0 0 0 3 3zm5-3a5 5 0 0 1-10 0H5a7 7 0 0 0 6 6.92V21h2v-3.08A7 7 0 0 0 19 11z"),micOff:te("M19 11h-2a5 5 0 0 1-.4 1.97l1.47 1.47A6.96 6.96 0 0 0 19 11zM15 11V5a3 3 0 0 0-5.94-.6L15 10.34zM4.27 3 3 4.27l6 6V11a3 3 0 0 0 4.52 2.59l1.46 1.46A5 5 0 0 1 7 11H5a7 7 0 0 0 6 6.92V21h2v-3.08a6.9 6.9 0 0 0 3.02-1.14L19.73 21 21 19.73z"),cam:te("M17 10.5V7a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-3.5l4 4v-11z"),camOff:te("M21 6.5l-4 4V7a1 1 0 0 0-1-1H9.82L21 17.18zM3.27 2 2 3.27 4.73 6H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h12c.21 0 .39-.08.54-.18L19.73 21 21 19.73z"),link:te("M3.9 12a3.1 3.1 0 0 1 3.1-3.1h4V7H7a5 5 0 0 0 0 10h4v-1.9H7A3.1 3.1 0 0 1 3.9 12zM8 13h8v-2H8zm9-6h-4v1.9h4a3.1 3.1 0 0 1 0 6.2h-4V17h4a5 5 0 0 0 0-10z"),leave:te("M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85a1 1 0 0 1-1.41-.02L.29 13.08a1 1 0 0 1 0-1.41C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67a1 1 0 0 1 0 1.41l-2.48 2.48a1 1 0 0 1-1.41.02 11.3 11.3 0 0 0-2.66-1.85 1 1 0 0 1-.56-.9v-3.1A15.3 15.3 0 0 0 12 9z"),mutedSmall:te("M19 11h-2a5 5 0 0 1-.4 1.97l1.47 1.47A6.96 6.96 0 0 0 19 11zM15 11V5a3 3 0 0 0-5.94-.6L15 10.34zM4.27 3 3 4.27l6 6V11a3 3 0 0 0 4.52 2.59l1.46 1.46A5 5 0 0 1 7 11H5a7 7 0 0 0 6 6.92V21h2v-3.08a6.9 6.9 0 0 0 3.02-1.14L19.73 21 21 19.73z")};function E(n,e={},t=[]){let i=document.createElement(n);for(let[r,s]of Object.entries(e))s!=null&&(r==="class"?i.className=s:r==="html"?i.innerHTML=s:r==="text"?i.textContent=s:r.startsWith("on")&&typeof s=="function"?i.addEventListener(r.slice(2),s):r in i&&typeof s!="string"?i[r]=s:i.setAttribute(r,s));for(let r of[].concat(t))r&&i.appendChild(typeof r=="string"?document.createTextNode(r):r);return i}var W=(n,e)=>n&&n.classList.toggle("dxr-call-hidden",!e);var bn="[inline3d/call]",qr="https://github.com/DisplayXR/displayxr-browser",xn=Object.freeze({accent:"theme.accent",tileAspect:"theme.tileAspect",inviteBase:"invite.base",updateUrl:"invite.updateUrl",browserUrl:"landing.browserUrl",maxLifted:"liftOptions.max",calibration:"openCamera({ calibration }) of '@displayxr/inline3d/camera' (pass the camera as `camera`)",rectify:"openCamera({ rectify }) of '@displayxr/inline3d/camera'",log:"debug: true (and diagnostics())",recoverSession:"nothing \u2014 a call always recovers the document's session (sharedInline3D())",wallOptions:"sharedInline3D(opts) \u2014 the document's wall is configured by the page",scrollIntoView:"nothing \u2014 always on with ui: true"}),wn=new Set;function Xr(n){wn.has(n)||(wn.add(n),console.warn(`${bn} option \`${n}\` is deprecated (removed in 1.31) \u2014 use ${xn[n]}`))}function Xt(n={}){for(let v of Object.keys(xn))n[v]!==void 0&&Xr(v);let e=n.theme&&typeof n.theme=="object"?n.theme:{},t=n.invite&&typeof n.invite=="object"?n.invite:{},i=n.landing&&typeof n.landing=="object"?n.landing:{},r=n.ui===void 0?!0:n.ui==="tiles"?"tiles":!!n.ui,s=r===!0,o=e.tileAspect!==void 0?e.tileAspect:n.tileAspect,a=typeof o=="number"&&o>.3&&o<4?o:16/9,l=n.room===void 0||n.room===null?"auto":n.room;if(l!=="auto"&&!ce(l)){let v=Se(l);if(!v)throw new Error(`@displayxr/inline3d/call: room "${l}" is not a valid room id (16-64 base64url chars) or invite link`);l=v}let c=n.liftOptions&&typeof n.liftOptions=="object"?{...n.liftOptions}:null,p=c&&c.max!==void 0?c.max:n.maxLifted;c&&delete c.max;let f=e.accent!==void 0?e.accent:n.accent,h={};for(let[v,y]of Object.entries(_n)){let b=v==="accent"?f:e[v];typeof b=="string"&&b?h[y]=v==="accent"?gn(b):b:typeof b=="number"&&v==="radius"&&(h[y]=`${b}px`)}let d=t.base!==void 0?t.base:n.inviteBase,m=t.updateUrl!==void 0?t.updateUrl:n.updateUrl,u=i.browserUrl!==void 0?i.browserUrl:n.browserUrl;return{room:l,signaling:n.signaling||fe(void 0,typeof n.key=="string"&&n.key?{key:n.key}:{}),iceServers:Array.isArray(n.iceServers)?n.iceServers:void 0,camera:n.camera===void 0?"auto":n.camera,format:n.format==="sbs"?"sbs":n.format==="mono"?"mono":void 0,calibration:n.calibration&&typeof n.calibration=="object"?{...n.calibration}:{},rectify:typeof n.rectify=="function"?n.rectify:null,audio:n.audio===void 0?!0:!!n.audio,autoConverge:n.autoConverge===void 0?!0:!!n.autoConverge,mono3D:ye(n.mono3D),maxPeers:Te(n.maxPeers===void 0?le:n.maxPeers),liftOptions:c&&Object.keys(c).length?c:null,maxLifted:Number.isFinite(+p)&&p!==null&&p!==void 0?Math.max(0,Math.min(le,Math.floor(+p))):le,layout:n.layout==="speaker"?"speaker":n.layout==="none"?"none":"grid",ui:r,chrome:s,autoJoin:n.autoJoin===void 0?!s:!!n.autoJoin,selfView:n.selfView===void 0?!0:!!n.selfView,tileAspect:a,cssVars:h,strings:e.strings&&typeof e.strings=="object"?{...e.strings}:null,invite:{base:typeof d=="string"?d:null,updateUrl:m===void 0?s:!!m},landing:{browserUrl:typeof u=="string"?u:qr,allow2D:i.allow2D===void 0?!0:!!i.allow2D},debug:!!n.debug,log:typeof n.log=="function"?n.log:n.debug?(v,y)=>console.log(`${bn} ${v} ${JSON.stringify(y)}`):null,_liftImporter:typeof n._liftImporter=="function"?n._liftImporter:void 0}}var Bs=Object.freeze(["normalizeCallOptions","newRoomId","isValidRoomId","buildInviteLink","normalizeHello","makeHello","routeFor","badgeFor","createLiveGate","convergenceShiftPx","lowPass","clampShift","eyeCropRect","mirrorSwapOps","mirrorSwapPixels","maxBitrateKbps","measureFocusDisparity","preferVideoCodecs","sortCodecCapabilities","VIDEO_CODEC_ORDER","MeshTransport","clampMaxPeers","qrEncode","roomKey","SIGNAL_PROTOCOL","WIRE_VERSION","CALL_SDK","PLATE_TEXT","CALL_ACCENTS","normalizeMono3D","resolveLift","createLiftPool","createFrameWatch","liftConvergenceFor","liftPriorityFor","setLiftPriority","defaultLiftSpecifier","LIFT_PRIORITY"]);var Jt="dxr-call:",Gr=["joined","left","peer","peerleft","state","display","speaker","quality","error","warning"],Gt="[inline3d/call] <dxr-call>",ue=n=>n!=null&&!/^(false|0|off|no)$/i.test(String(n).trim()),Sn=n=>{if(n==null||String(n).trim()==="")return;let e=/^\s*([0-9.]+)\s*\/\s*([0-9.]+)\s*$/.exec(String(n)),t=e?+e[1]/+e[2]:+n;return Number.isFinite(t)?t:void 0},N=n=>n==null||String(n).trim()===""?void 0:String(n).trim();function Kt(n){let e=typeof n=="function"?n:l=>n&&typeof n.getAttribute=="function"?n.getAttribute(l):null,t={},i=(l,c)=>{c!==void 0&&(t[l]=c)};i("room",N(e("room")));let r=N(e("signaling"));r&&(t.signaling=fe(r,N(e("key"))?{key:N(e("key"))}:{})),i("key",N(e("key"))),i("camera",N(e("camera"))),i("layout",N(e("layout"))),i("maxPeers",Sn(e("max-peers")));let s=N(e("ui"));ue(e("no-ui"))?t.ui=!1:s==="tiles"&&(t.ui="tiles"),ue(e("auto-join"))&&(t.autoJoin=!0);let o=N(e("mono3d"));o&&/^(off|false|0|no)$/i.test(o)&&(t.mono3D="off"),ue(e("no-audio"))&&(t.audio=!1),ue(e("no-self-view"))&&(t.selfView=!1),ue(e("no-auto-converge"))&&(t.autoConverge=!1);let a={accent:N(e("accent")),tileAspect:Sn(e("tile-aspect"))};return(a.accent!==void 0||a.tileAspect!==void 0)&&(t.theme=Object.fromEntries(Object.entries(a).filter(([,l])=>l!==void 0))),N(e("invite-base"))&&(t.invite={base:N(e("invite-base"))}),N(e("browser-url"))&&(t.landing={browserUrl:N(e("browser-url"))}),ue(e("debug"))&&(t.debug=!0),t}var Jr=typeof HTMLElement=="function"?HTMLElement:class{},pe=class n extends Jr{static mount=null;constructor(){super(),this.options=null,this.call=null,this.ready=null,this._gen=0,this._off=[],this._pending=null}connectedCallback(){if(this.call||this._pending)return;let e=++this._gen,t={...Kt(this),...this.options&&typeof this.options=="object"?this.options:{}},i=this.constructor.mount||n.mount||Yt;this._pending=new Promise(r=>r(i(this,t))).then(r=>{if(this._pending=null,e!==this._gen)return r.leave(),null;if(this.call=r,this._off=Gr.map(s=>r.on(s,o=>this._dispatch(s,o))),this._off.push(r.on("error",s=>console.warn(`${Gt} ${s.code}: ${s.message}`))),this._dispatch("ready",{call:r}),r.state==="in-call"){this._dispatch("joined",{room:r.room,id:r.id});for(let s of r.peers)this._dispatch("peer",{id:s.id})}return r},r=>{throw this._pending=null,this._dispatch("error",{code:"mount-failed",message:String(r&&r.message||r),error:r||null}),console.warn(`${Gt} mount failed: ${String(r&&r.message||r)}`),r}),this.ready=this._pending,this.ready.catch(()=>{})}disconnectedCallback(){this._gen++;let e=this.call;this.call=null,e&&e.leave();for(let t of this._off)try{t()}catch{}this._off=[]}_dispatch(e,t){typeof CustomEvent!="function"||typeof this.dispatchEvent!="function"||this.dispatchEvent(new CustomEvent(Jt+e,{detail:t,bubbles:!0,composed:!0}))}};function et(n="dxr-call",e=globalThis.customElements){if(!e||typeof e.define!="function")return!1;let t=e.get(n);return t?(t!==pe&&console.warn(`${Gt} <${n}> is already defined by another class; leaving it`),!1):(e.define(n,pe),!0)}var G="[inline3d/call]",Kr=2e3,Yr=2500,Zr=500,Zt=.02,Qr=4,es=2,ts=200,Mn=240,is=new Set(["I420","I420A","I422","I444","NV12"]);async function Tn(n,e,t={}){if(!e||typeof e.appendChild!="function")throw new TypeError("@displayxr/inline3d/call: addCall(wall, container, opts) needs a container element");let i=Xt(t);if(!i.signaling||typeof i.signaling.join!="function")throw new TypeError("@displayxr/inline3d/call: opts.signaling must be a SignalingAdapter \u2014 dxrSignaling([url]) or your own");let r=new Qt(n,e,i);return await r._init(),r.handle}async function Yt(n,e={}){if(!n||typeof n.appendChild!="function")throw new TypeError("@displayxr/inline3d/call: mountCall(el, opts) needs a container element");let{wall:t,...i}=e,r=t||await Fe(i.wallOptions);return Tn(r,n,i)}var Qt=class{constructor(e,t,i){this.o=i,this.t=vn(i.strings),this.container=t,this.wall=e||null,this.wallLive=!!(e&&e.supported),this.weaveLive=!1,this.camStatus="pending",this.id=Ai(),this.room=i.room==="auto"?Se(globalThis.location):i.room,this.state="idle",this.tiles=new Map,this.listeners=new Map,this.local=null,this.muted=!1,this.camOff=!1,this.depth=0,this.speakerId=null,this.transport=null,this._raf=0,this._statsTimer=0,this._hintGate=kt(bt),this.mono3D=i.mono3D,this.mono3DOn=i.mono3D!=="off",this.liftApi=null,this.liftPool=null,this._liftP=null,this.liftProven=!1,this.liftMissing=!1,this._liftWarned=!1,this._frameWatch=st(),this.handle=this._makeHandle(),this.wallLive&&this._hookWall(this.wall)}get woven(){return!!(this.wall&&this.wall.supported&&this.wallLive)}log(e,t={}){this.o.log&&this.o.log(e,t)}emit(e,t){let i=this.listeners.get(e);if(i)for(let r of[...i])try{r(t)}catch(s){console.error(`${G} '${e}' listener threw`,s)}}error(e,t,i){this.log("error",{code:e,message:t}),this.listeners.get("error")?.size||console.warn(`${G} ${e}: ${t}`),this.emit("error",{code:e,message:t,error:i||null})}warning(e,t){this.log("warning",{code:e,message:t}),console.warn(`${G} ${e}: ${t}`),this.emit("warning",{code:e,message:t})}async _init(){this._buildDom(),this.wallLive&&this._ensureLift(),await this._openMedia(this.o.camera),this._startLoop(),this.o.autoJoin?await this.join():this._setState("lobby")}async _openMedia(e,t,{keepOnFail:i=!1}={}){let r=(h,d)=>this.log(h,d),s=null,o=null,a=Ze(e)?e:null;try{if(s=a||await zt({prefer:e,format:t||this.o.format,calibration:this.o.calibration,rectify:this.o.rectify||void 0,log:r}),a&&a.state!=="live")throw Object.assign(new Error("the camera given is not live"),{code:"no-camera",skipped:[]})}catch(h){o=h;let d=h.code==="camera-busy";if(this.error(d?"camera-busy":h.code||"no-camera",d?`${this.t("cameraBusy")}. Joining audio-only.`:`no camera: ${h.message}. Joining audio-only.`,h),i&&this.local&&this.local.videoTrack)return this.local;this.camStatus=d?"busy":"none"}s&&(this.camStatus="ok"),s&&s.rectifyError&&this.error("rectify-failed",`rectify() threw \u2014 sending the raw pair: ${s.rectifyError.message}`,s.rectifyError);let l=this.local?this.local.audioTrack:null;this.o.audio&&!l&&(l=await zi({log:r})),l&&(l.enabled=!this.muted);let c=s&&s.stream.getVideoTracks()[0]||null;if(c){try{c.contentHint="detail"}catch{}c.enabled=!this.camOff}let p=new MediaStream([c,l].filter(Boolean)),f=this.local;return this.local={stream:p,cam:s,camStream:s?s.stream:null,video:s?s.video:null,videoTrack:c,audioTrack:l,format:s?s.format:"mono",width:s?s.width:0,height:s?s.height:0,calibration:s?s.calibration:{},owned:s?s.owned&&s!==a:!1,label:s?s.label:"",skipped:s?s.skipped:o?.skipped||[]},s&&s!==f?.cam&&(this._camEndedOff?.(),this._camEndedOff=s.on("ended",()=>{this.local?.cam===s&&(this.local.videoTrack=null,this.camStatus="none",this.error("no-camera",'the camera ended (revoked, unplugged, or taken by another app). Audio-only until "Retry camera".'),this.transport?.broadcast(this.stateMsg()),this._refreshSelf(),this._refreshBar())})),this.log("camera",{format:this.local.format,width:this.local.width,height:this.local.height,label:this.local.label,skipped:this.local.skipped.length}),f&&f.owned&&f.cam&&f.cam!==s&&f.cam.close(),this._refreshSelf(),this._refreshLobby(),this.local}hello(){let e=this.local||{};return Mt({format:e.format,width:e.width,height:e.height,baselineMm:e.calibration?.baselineMm,hfovDeg:e.calibration?.hfovDeg,rectified:!!e.calibration?.rectified})}stateMsg(){return{type:"state",muted:this.muted,cameraOff:this.camOff||!this.local?.videoTrack,speaking:!!this._selfSpeaking}}async join(){if(this.state==="joining"||this.state==="in-call")return this.handle;if(this.state==="left"&&!this.local?.videoTrack&&await this._openMedia(this.o.camera),this.room||(this.room=xt(),this.log("room-created",{})),this.o.invite.updateUrl&&globalThis.history&&globalThis.location)try{history.replaceState(history.state,"",He(location.href,this.room))}catch{}this._setState("joining");let e=new ke({signaling:this.o.signaling,id:this.id,maxPeers:this.o.maxPeers,iceServers:this.o.iceServers,log:(i,r)=>this.log(i,r)});this.transport=e;let t=null;try{t=await e.start({room:this.room,localStream:this.local.stream,sendFormat:this.local.format,onPeer:i=>this._onPeer(i),onPeerLeft:(i,r)=>this._onPeerLeft(i,r),onStream:(i,r)=>this.tiles.get(i)?.setStream(r),onMessage:(i,r)=>this._onMessage(i,r),onPeerState:(i,r)=>{this.tiles.get(i)?.setConn(r),this.emit("state",{id:i,state:r})},onRefused:i=>this.log("refused-peer",{id:i}),onGhost:(i,r)=>this._onGhost(i,r),onSignalingState:(i,r)=>{this.log("signaling",{state:i}),i==="closed"&&r&&this.error(r.code||"signaling-closed",r.message,r)}})}catch(i){throw this.transport=null,i&&i.code==="room-full"?(this._setState("full"),this.error("room-full",i.message,i)):(this._setState("lobby"),this.error(i.code||"join-failed",`could not join: ${i.message}`,i)),i}if(this._setState("in-call"),this.o.chrome)try{this.container.scrollIntoView?.({block:"start",behavior:"instant"}),this._fitGrid()}catch{}return this._startStats(),this._pagehide=()=>this.leave("pagehide"),globalThis.addEventListener?.("pagehide",this._pagehide),this.log("joined",{id:this.id,peers:this.tiles.size}),this.emit("joined",{room:this.room,id:this.id}),setTimeout(()=>{this.transport===e&&this._reportTurn(t)},0),this.handle}_reportTurn(e){let t=e&&e.turn;!t||typeof t!="object"||(t.status==="off"&&t.reason==="cap"?this.error("turn-cap","relay (TURN) capacity for this month is used up; direct connections still work, but a participant behind a strict NAT may be unreachable",null):(t.reason==="budget"||t.reason==="rate")&&this.warning("turn-shed",t.reason==="rate"?"no relay (TURN) for this session: too many credential requests from this address this hour":"no relay (TURN) for this anonymous session: the hosted service is near its monthly relay budget (a publishable key keeps TURN)"))}_onPeer(e){if(this.tiles.has(e))return;let t=new tt(this,e);this.tiles.set(e,t),this._layout(),this.emit("peer",{id:e})}_onGhost(e,t){let i=this.tiles.get(e);if(t&&!i){let r=new tt(this,e);r.ghost=!0,this.tiles.set(e,r),r.setConn("unreachable"),this._layout()}else!t&&i&&i.ghost&&(i.destroy(),this.tiles.delete(e),this._layout())}_onPeerLeft(e,t){let i=this.tiles.get(e);i&&(i.setConn("left"),this.emit("peerleft",{id:e,reason:t}),i.leaveTimer=setTimeout(()=>{i.destroy(),this.tiles.get(e)===i&&this.tiles.delete(e),this.speakerId===e&&this._setSpeaker(null),this._layout()},Yr))}_onMessage(e,t){let i=this.tiles.get(e);if(!i||!t)return;if(t.type==="__open"){this.transport.send(e,this.hello()),this.transport.send(e,this.stateMsg()),i.onChannelOpen();return}let r=St(t);if(r)return i.setHello(r);let s=Et(t);if(s)return i.setHint(s);let o=Ii(t);if(o)return i.setRemoteState(o)}inviteLink(){if(!this.room)return null;let e=this.o.invite.base||(globalThis.location?location.href:"");return He(e,this.room)}mute(e){return this.muted=e===void 0?!this.muted:!!e,this.local?.audioTrack&&(this.local.audioTrack.enabled=!this.muted),this.transport?.broadcast(this.stateMsg()),this._refreshBar(),this.log("mute",{muted:this.muted}),this.muted}setCameraOff(e){return this.camOff=e===void 0?!this.camOff:!!e,this.local?.videoTrack&&(this.local.videoTrack.enabled=!this.camOff),this.transport?.broadcast(this.stateMsg()),this._refreshBar(),this._refreshSelf(),this.camOff}setDepth(e){let t=e==null||!Number.isFinite(+e)?0:Math.max(-1,Math.min(1,+e));this.depth=t;for(let i of this.tiles.values())i.conv.depth=t;return this.liftPool?.setDepth(t),this.ui?.depth&&+this.ui.depth.value!==t&&(this.ui.depth.value=String(t)),t}async setCamera(e,{format:t}={}){let i=this.local?.format,r=await this._openMedia(e,t,{keepOnFail:!0});return this.transport&&(await this.transport.replaceTrack("video",r.videoTrack,r.stream),await this.transport.setSendFormat(r.format),this.transport.broadcast(this.hello()),this.transport.broadcast(this.stateMsg())),i!==r.format&&this.log("send-format",{format:r.format}),{format:r.format,width:r.width,height:r.height,label:r.label}}retryCamera(){return this.setCamera(this.o.camera,{format:this.o.format})}sendHint(e){if(!this._hintGate(performance.now()))return!1;let t=Et({type:"hint",subjectZmm:e});return t?(this.transport?.broadcast(t),!0):!1}leave(e="left"){if(this.state!=="left"){globalThis.removeEventListener?.("pagehide",this._pagehide),this.transport?.stop(),this.transport=null;for(let t of this.tiles.values())t.destroy();this.tiles.clear(),this.liftPool?.releaseAll(),clearInterval(this._statsTimer),this._setSpeaker(null),this.local&&(this._camEndedOff?.(),this._camEndedOff=null,this.local.stream.getTracks().forEach(t=>t.stop()),this.local.owned&&this.local.cam?this.local.cam.close():this.local.cam&&this.self?.detach(),this.local.videoTrack=null,this.local.audioTrack=null),this.self?.detach(),this._unhookWall(),this._setState("left"),this._layout(),this.emit("left",{room:this.room,reason:e})}}_hookWall(e){if(!e||!e.session||typeof e.session.addEventListener!="function")return;let t=e.close;this._wallHook={w:e,orig:t,pageClosed:!1};let i=this._wallHook;e.close=(...r)=>(i.pageClosed=!0,t.apply(e,r)),i.onEnd=()=>this._sessionEnded(i),e.session.addEventListener("end",i.onEnd),this._watchLive(e)}_watchLive(e){this.weaveLive=!1;let t=e.session;if(!t||typeof t.requestAnimationFrame!="function"){this.weaveLive=!0;return}let i=Rt(),r=performance.now(),s=(o,a)=>{if(e!==this.wall||!this.wallLive||this.state==="left")return;let l=null;if(e.refSpace)try{let c=a.getViewerPose(e.refSpace);l=c&&c.views?c.views.length:0}catch{l=0}if(!i.feed(l)){try{t.requestAnimationFrame(s)}catch{}return}this.weaveLive=!0,this.log("weave-live",{ms:Math.round(performance.now()-r)});for(let c of this.tiles.values())(c.route==="woven-sbs"||c.route==="lifted")&&c.reroute(!0);this.self&&this.self.route==="woven-sbs"&&this.self.reroute(!0),this._layout()};try{t.requestAnimationFrame(s)}catch{this.weaveLive=!0}}_unhookWall(){let e=this._wallHook;if(e){this._wallHook=null,e.w.close!==e.orig&&(e.w.close=e.orig);try{e.w.session.removeEventListener("end",e.onEnd)}catch{}}}_sessionEnded(e){if(this._wallHook===e){this.wallLive=!1,this.weaveLive=!1,this.log("session-ended",{byPage:e.pageClosed});for(let t of this.tiles.values())t.onWallLost();if(this.self?.onWallLost(),e.pageClosed||this.state==="left"){this._unhookWall();return}this.error("session-ended","the inline-3D session ended; tiles are flat while it is re-opened"),this._unhookWall(),this._recoverWall(0)}}_recoverWall(e){this.state==="left"||e>10||setTimeout(async()=>{if(this.state==="left")return;let t=null;try{t=await Fe()}catch{t=null}if(!t||!t.supported)return this._recoverWall(e+1);this.wall=t,this.wallLive=!0,this._hookWall(t),this.log("session-recovered",{attempt:e});for(let i of this.tiles.values())i.reroute(!0);this.self?.reroute(!0)},B(e,{baseMs:1e3,maxMs:15e3}))}_startLoop(){let e=0,t=i=>{this._raf=requestAnimationFrame(t);for(let r of this.tiles.values())r.paint();e&&this.liftPool&&this.liftPool.anyWeb&&this._watchFrames(i-e),e=i};this._raf=requestAnimationFrame(t)}_watchFrames(e){let t=this._frameWatch.feed(e);if(!t)return;let i={degraded:t==="degraded",frameMs:Math.round(this._frameWatch.frameMs*10)/10,tiles:this.liftPool.size};this.log("lift-frame-time",i),t==="degraded"&&console.warn(`${G} lifted tiles are slowing the page (~${Math.round(1e3/i.frameMs)} fps with ${i.tiles} lifted) \u2014 setMono3D(false) shows mono peers flat`),this.emit("quality",{id:null,in:null,out:null,lift:i})}_ensureLift(){if(!this.mono3DOn)return Promise.resolve(null);if(!this._liftP){let e=(r,s)=>this.log(r,s),t=this.o.liftOptions,i={webFallback:!0,...t&&t.models?{models:t.models}:{}};this._liftP=nt(this.mono3D,{log:e,capsOpts:i,...this.o._liftImporter?{importer:this.o._liftImporter}:{}}).then(r=>(this.liftApi=r,r.lift?(this.liftPool=ot({lift:r.lift,max:this.o.maxLifted,log:e,options:this.o.liftOptions}),this.liftPool.setDepth(this.depth),this.liftPool.setSpeaker(this.speakerId),!r.caps&&r.capabilities&&Promise.resolve().then(()=>r.capabilities(i)).then(s=>{r.caps=s||null,this._refreshLobby()}).catch(()=>{})):r.reason==="import-failed"||r.reason==="no-lift-export"?this.liftMissing=!0:r.reason!=="off"&&console.info(`${G} mono\u21923D unavailable (${r.reason}) \u2014 mono participants are shown flat`),this._rerouteMono(),this._refreshLobby(),r))}return this._liftP}_warnLiftMissing(){this._liftWarned||!this.liftMissing||!this.mono3DOn||(this._liftWarned=!0,this.warning("lift-not-bundled","a 2D participant is on a 3D display but the 2D\u21923D module could not be imported from this build, so they stay flat. Import it explicitly \u2014 `import { lift } from '@displayxr/inline3d/lift'; mountCall(el, { mono3D: lift })` \u2014 or use `@displayxr/inline3d/call/full`, which bundles it."))}_rerouteMono(){for(let e of this.tiles.values())e.format&&e.format!=="sbs"&&e.reroute(!1)}setMono3D(e){let t=e===void 0?!this.mono3DOn:!!e;return t===this.mono3DOn||(this.mono3DOn=t,t&&this.mono3D==="off"&&(this.mono3D="auto"),this._frameWatch.reset(),this.log("mono3d",{on:t}),this._rerouteMono(),t&&this.wallLive&&this._ensureLift(),this._refreshLobby()),t}_liftHint(){if(!this.wallLive)return"";let e=this.t;if(!this.mono3DOn)return e("liftOff");let t=this.liftApi;if(!t)return e("liftChecking");if(!t.lift)return this.liftMissing?e("liftMissing"):e("liftNoProvider");let i=t.caps;return i&&i.native?e("liftNative",{provider:i.provider?`, ${i.provider}`:""}):i&&i.webFallback&&i.webFallback.webgpu?e("liftWeb"):this.liftProven?e("liftProven"):e("liftUnproven")}_mono3DInfo(){let e=this.liftApi,t=e&&e.caps;return Object.freeze({on:this.mono3DOn,state:this.mono3DOn?e?e.lift?"ready":"unavailable":this._liftP?"loading":"idle":"off",reason:e?e.reason:null,native:t?!!t.native:null,provider:t&&t.provider||null,lifted:this.liftPool?this.liftPool.size:0,max:this.o.maxLifted,proven:this.liftProven})}_startStats(){clearInterval(this._statsTimer);let e=0;this._statsTimer=setInterval(()=>this._stats(++e%4===0),Zr)}async _stats(e){if(!this.transport)return;let t=null,i=0;for(let[o,a]of this.tiles){let l=this.transport.peerConnection(o);if(!l)continue;let c;try{c=await l.getStats()}catch{continue}let p={};c.forEach(d=>{d.type==="codec"&&(p[d.id]=d.mimeType)});let f={in:null,out:null};c.forEach(d=>{if(d.type==="inbound-rtp"&&d.kind==="audio"&&typeof d.audioLevel=="number"&&(a.level=Math.max(d.audioLevel,(a.level||0)*.6)),d.type==="media-source"&&d.kind==="audio"&&typeof d.audioLevel=="number"&&(i=Math.max(i,d.audioLevel)),!!e){if(d.type==="inbound-rtp"&&d.kind==="video"){let m=a._prevIn;f.in={width:d.frameWidth||0,height:d.frameHeight||0,fps:d.framesPerSecond||0,codec:p[d.codecId]||null,kbps:m?Math.round((d.bytesReceived-m.bytes)*8/(d.timestamp-m.t)):null,dropped:d.framesDropped||0,decoder:d.decoderImplementation||null},a._prevIn={bytes:d.bytesReceived,t:d.timestamp}}else if(d.type==="outbound-rtp"&&d.kind==="video"){let m=a._prevOut;f.out={width:d.frameWidth||0,height:d.frameHeight||0,fps:d.framesPerSecond||0,codec:p[d.codecId]||null,kbps:m?Math.round((d.bytesSent-m.bytes)*8/(d.timestamp-m.t)):null,limitation:d.qualityLimitationReason||null,encoder:d.encoderImplementation||null},a._prevOut={bytes:d.bytesSent,t:d.timestamp}}}}),e&&(f.in||f.out)&&(a.quality=f,this.emit("quality",{id:o,...f}));let h=a.remote.muted?0:a.level||0;a.setSpeaking(h>Zt||a.remote.speaking),h>Zt&&(!t||h>t.lvl)&&(t={id:o,lvl:h})}let r=t?t.id:null;r&&r!==this.speakerId?(this._challengeTicks=this._challenger===r?(this._challengeTicks||0)+1:1,this._challenger=r,this._challengeTicks>=2&&this._setSpeaker(r)):(this._challenger=null,this._challengeTicks=0);let s=!this.muted&&i>Zt;s!==!!this._selfSpeaking&&(this._selfSpeaking=s,this.transport?.broadcast(this.stateMsg()),this.self?.setSpeaking(s))}_setSpeaker(e){e!==this.speakerId&&(this.speakerId=e,this._challengeTicks=0,this.liftPool?.setSpeaker(e),this.emit("speaker",{id:e}),this.o.layout==="speaker"&&this._layout())}_fitGrid(){let e=this.ui;if(!e||!this.o.chrome||typeof globalThis.innerHeight!="number")return;let t=this.container.getBoundingClientRect?.(),i=e.grid.getBoundingClientRect?.();if(!t||!i||!i.height)return;let r=Math.max(160,Math.floor(globalThis.innerHeight-Math.max(0,t.top)-(t.height-i.height)-8)),s=parseFloat(this.container.style.getPropertyValue("--dxr-call-fit"))||0;Math.abs(r-s)>2&&this.container.style.setProperty("--dxr-call-fit",`${r}px`),this._fitHooked||(this._fitHooked=!0,globalThis.addEventListener?.("resize",()=>this._fitGrid()))}_setState(e){this.state=e,this.log("state",{state:e}),this._layout()}_buildDom(){let e=this.container,t=this.t;yn(e.ownerDocument||document),e.classList.add("dxr-call-host");for(let[r,s]of Object.entries(this.o.cssVars))e.style.setProperty(r,s);let i=this.ui={};i.banner=E("div",{class:"dxr-call-banner dxr-call-hidden",part:"banner"},[E("span",{text:t("banner2D")}),E("a",{href:this.o.landing.browserUrl,target:"_blank",rel:"noopener",text:t("bannerLink")})]),i.grid=E("div",{class:"dxr-call-grid",part:"grid","data-layout":this.o.layout,"data-n":"0"}),i.panel=E("div",{class:"dxr-call-panel dxr-call-hidden",part:"lobby"}),i.selfSlot=E("div",{class:"dxr-call-self",part:"self"}),i.bar=E("div",{class:"dxr-call-bar",part:"bar"}),i.foot=E("div",{class:"dxr-call-foot"},[i.selfSlot,i.bar]),i.invite=E("div",{class:"dxr-call-panel dxr-call-hidden",part:"invite"}),this.o.chrome||W(i.bar,!1),e.append(i.banner,i.panel,i.grid,i.invite,i.foot),this.o.selfView?this.self=new ei(this,i.selfSlot):W(i.selfSlot,!1),this.o.chrome&&this._buildBar()}_buildBar(){let e=this.ui,t=this.t,i=(r,s,o,a="")=>E("button",{class:`dxr-call-ib ${a}`,type:"button","aria-label":r,title:r,html:s,onclick:o});e.mic=i(t("mute"),q.mic,()=>this.mute()),e.cam=i(t("cameraOff"),q.cam,()=>this.local?.videoTrack?this.setCameraOff():this.retryCamera().catch(()=>{})),e.depth=E("input",{type:"range",min:"-1",max:"1",step:"0.05",value:"0","aria-label":t("depth")}),e.depth.addEventListener("input",()=>this.setDepth(+e.depth.value)),e.depth.addEventListener("dblclick",()=>this.setDepth(0)),e.inviteBtn=i(t("invite"),q.link,()=>{this._showInvite=!this._showInvite,this._layout()}),e.leave=i(t("leave"),q.leave,()=>this.leave(),"dxr-call-ib--leave"),e.bar.append(e.mic,e.cam,E("label",{class:"dxr-call-depth"},[t("depth"),e.depth]),e.inviteBtn,e.leave)}_refreshBar(){let e=this.ui;if(!e||!e.mic)return;let t=this.t;e.mic.innerHTML=this.muted?q.micOff:q.mic,e.mic.setAttribute("aria-pressed",String(this.muted)),e.mic.title=this.muted?t("unmute"):t("mute");let i=!this.local?.videoTrack;e.cam.innerHTML=this.camOff||i?q.camOff:q.cam,e.cam.setAttribute("aria-pressed",String(this.camOff||i)),e.cam.title=i?this.camStatus==="busy"?t("cameraBusyRetry",{cameraBusy:t("cameraBusy")}):t("cameraRetry"):this.camOff?t("cameraOn"):t("cameraOff")}_refreshSelf(){this.self?.update()}_refreshLobby(){(this.state==="lobby"||this.state==="idle")&&this._layout()}_renderInvite(e,t,i){e.replaceChildren();let r=this.inviteLink();if(!r)return;let s=this.t,o=E("input",{type:"text",readOnly:!0,value:r,"aria-label":s("inviteLink")});o.addEventListener("focus",()=>o.select());let a=E("button",{class:"dxr-call-btn dxr-call-btn--primary",type:"button",text:s("copyLink")});a.addEventListener("click",async()=>{try{await navigator.clipboard.writeText(r),a.textContent=s("copied")}catch{o.select(),a.textContent=s("pressCopy")}setTimeout(()=>a.textContent=s("copyLink"),1800)});let l=E("canvas",{"aria-label":s("qrLabel"),role:"img"});try{fn(l,r,{px:4})}catch{l.style.display="none"}e.append(E("h3",{text:t}),E("p",{text:i}),E("div",{class:"dxr-call-invite"},[E("div",{class:"dxr-call-row",style:"flex:1 1 280px"},[o,a]),l]))}_layout(){let e=this.ui;if(!e)return;let t=this.container,i=this.t,r=this.o.chrome&&(this.state==="lobby"||this.state==="idle"||this.state==="full"||this.state==="left");t.classList.toggle("dxr-call-host--lobby",r),W(e.banner,this.o.chrome&&!this.woven);let s=this.tiles.size;e.grid.dataset.n=String(Math.min(s,4)),W(e.grid,s>0&&this.state!=="left");let o=this.o.layout==="speaker"?this.speakerId||[...this.tiles.keys()][0]:null;for(let[c,p]of this.tiles)p.el.classList.toggle("dxr-call-tile--main",c===o);if(!this.o.chrome)return;this._refreshBar(),queueMicrotask(()=>this._fitGrid());let a=e.panel;if(r){W(a,!0),a.replaceChildren();let c=this.local,p=!!this.room,f=this.state==="full"?i("lobbyFullTitle"):this.state==="left"?i("lobbyLeftTitle"):i(p?"lobbyJoinTitle":"lobbyStartTitle"),h={width:c?.width||0,height:c?.height||0},d=this.camStatus==="busy"?i("kindBusy"):!c||!c.videoTrack?i("kindNone"):c.format==="sbs"?i("kindSbs",h):i("kindMono",h),m=this.state==="full"?i("lobbyFullText",{maxPeers:this.o.maxPeers}):`${i("lobbyText",{camera:c?.label||i("cameraDefault"),kind:d})}${this._liftHint()?` ${this._liftHint()}`:""}`,u=E("button",{class:"dxr-call-btn dxr-call-btn--primary",type:"button",text:this.state==="left"?i("rejoin"):i(p?"join":"start")});u.addEventListener("click",()=>this.join().catch(()=>{}));let v=E("select",{class:"dxr-call-select","aria-label":i("cameraSelect")});this._fillCameras(v),v.addEventListener("change",()=>this.setCamera(v.value).catch(b=>this.error("camera-failed",b.message,b)));let y=!c||!c.videoTrack?E("button",{class:"dxr-call-btn",type:"button",text:i("retryCamera")}):null;y?.addEventListener("click",()=>this.retryCamera().catch(()=>{})),a.append(E("h3",{text:f}),E("p",{text:m}),E("div",{class:"dxr-call-row"},[this.state==="full"?null:u,y,v]))}else this.state==="in-call"&&s===0?(W(a,!0),this._renderInvite(a,i("waitingTitle"),i("waitingText"))):this.state==="joining"?(W(a,!0),a.replaceChildren(E("p",{text:i("joining")}))):W(a,!1);let l=this.state==="in-call"&&s>0&&this._showInvite;l&&!e.invite.childElementCount&&this._renderInvite(e.invite,i("inviteTitle"),i("inviteText")),W(e.invite,l),l||e.invite.replaceChildren(),e.inviteBtn?.setAttribute("aria-pressed",String(!!l))}diagnostics(){let e=this.local;return{sdk:wt,wire:ze,state:this.state,wall:this.wall,wallLive:this.wallLive,weaveLive:this.weaveLive,woven:this.woven,local:e?{format:e.format,width:e.width,height:e.height,label:e.label,calibration:e.calibration,owned:e.owned,skipped:e.skipped,camera:e.cam||null,stream:e.stream}:null,hello:this.hello(),transport:this.transport,peers:[...this.tiles.values()].map(t=>t.diag()),self:this.self?this.self.diag():null,mono3D:{...this._mono3DInfo(),lift:this.liftApi,pool:this.liftPool?this.liftPool.list():[]},speaker:this.speakerId,depth:this.depth,options:this.o,kill:t=>this.transport?._debugKill(t)}}async _fillCameras(e){let t=[];try{t=(await navigator.mediaDevices.enumerateDevices()).filter(r=>r.kind==="videoinput")}catch{}let i=this.local?.videoTrack?.getSettings?.().deviceId;e.replaceChildren(...t.map((r,s)=>E("option",{value:r.deviceId,text:r.label||`Camera ${s+1}`}))),i&&(e.value=i),W(e,t.length>1)}_makeHandle(){let e=this,t={format:"display",session:null},i={get room(){return e.room},get id(){return e.id},get state(){return e.state},get localFormat(){return e.local?e.local.format:null},get muted(){return e.muted},get cameraOff(){return e.camOff},get depth(){return e.depth},get speaker(){return e.speakerId},get camera(){return e.camStatus},get mono3D(){return e._mono3DInfo()},get peers(){return Object.freeze([...e.tiles.values()].map(s=>s.info()))},join:()=>e.join().then(()=>{}),inviteLink:()=>e.inviteLink(),mute:s=>e.mute(s),setCameraOff:s=>e.setCameraOff(s),setCamera:(s,o)=>e.setCamera(s,o),setDepth:s=>e.setDepth(s),retryCamera:()=>e.retryCamera(),setMono3D:s=>e.setMono3D(s),leave:()=>e.leave("left"),tile:s=>e.tiles.get(s)?.el||null,diagnostics:()=>e.diagnostics(),on(s,o){if(typeof o!="function")throw new TypeError(`${G} on() takes a function`);if(s in t&&!e._eventWarned?.has(s)){(e._eventWarned||=new Set).add(s);let a=t[s];console.warn(`${G} the '${s}' event is deprecated (removed in 1.31)${a?` \u2014 listen for '${a}'`:" \u2014 it is internal now; diagnostics() has the wall"}`)}return e.listeners.has(s)||e.listeners.set(s,new Set),e.listeners.get(s).add(o),()=>e.listeners.get(s)?.delete(o)},off(s,o){e.listeners.get(s)?.delete(o)}},r={wall:["diagnostics().wall (or the wall you passed / sharedInline3D())",()=>e.wall],format:["localFormat",()=>i.localFormat],sendHint:["nothing \u2014 auto-convergence superseded it",()=>s=>e.sendHint(s)],_debug:["diagnostics()",()=>({transport:e.transport,kill:s=>e.transport?._debugKill(s)})]};for(let[s,[o,a]]of Object.entries(r))Object.defineProperty(i,s,{enumerable:!1,configurable:!0,get(){return e._handleWarned?.has(s)||((e._handleWarned||=new Set).add(s),console.warn(`${G} handle.${s} is deprecated (removed in 1.31) \u2014 use ${o}`)),a()}});return i}};function ns(n){let e=Math.min(globalThis.devicePixelRatio||1,2),t=Math.round((n.clientWidth||0)*e),i=Math.round((n.clientHeight||0)*e);return!t||!i?!1:((n.width!==t||n.height!==i)&&(n.width=t,n.height=i),!0)}function En(n,e,{eyeHalf:t=null,mirror:i=!1}={}){if(!ns(n))return;let r=n.getContext("2d"),s=e.videoWidth,o=e.videoHeight;if(!s||!o||(e.readyState||0)<2)return;let a=t===null?s:s/2,l=X(a,o,n.width/n.height,0,0);r.save(),i&&(r.translate(n.width,0),r.scale(-1,1)),r.drawImage(e,(t||0)*a+l.sx,l.sy,l.sw,l.sh,0,0,n.width,n.height),r.restore()}var tt=class{constructor(e,t){this.call=e,this.id=t,this.hello=null,this.format=null,this.route=null,this.routedKey=null,this.handle=null,this.conn="connecting",this.remote={muted:!1,cameraOff:!1,speaking:!1},this.level=0,this.speaking=!1,this.quality=null,this.conv=xe(),this.autoTrack=qe(),this.autoFocus=Ce(),this.autoAt=0,this.autoCanvas=null,this.autoLocked=!1,this.autoStats={n:0,ms:0,readMs:0,method:null,via:null},this.autoPending=!1,this.autoGen=0,this.destroyed=!1,this.conv.depth=e.depth,this.hintGate=kt(bt),this.layerFails=0,this.forceFlat=!1,this.lifted=!1,this.liftHandle=null,this.liftLive=!1,this.liftFailed=!1,this.liftFails=0,this.visible=!0,this.video=Object.assign(document.createElement("video"),{muted:!0,playsInline:!0,autoplay:!0}),this.audio=Object.assign(document.createElement("audio"),{autoplay:!0}),this.video.addEventListener("playing",()=>this._maybeRoute()),this.video.addEventListener("loadeddata",()=>this._maybeRoute()),this.video.addEventListener("resize",()=>this._maybeRoute()),this.canvas=E("canvas"),this.cover=E("div",{class:"dxr-call-cover dxr-call-hidden"}),this.badge=E("div",{class:"dxr-call-badge",part:"badge"}),this.plate=E("div",{class:"dxr-call-state",part:"plate",text:e.t("connecting")}),this.stage=E("div",{class:"dxr-call-stage"},[this.canvas,this.cover,this.badge,this.plate]),this.stage.style.aspectRatio=String(e.o.tileAspect),this.el=E("div",{class:"dxr-call-tile",part:"tile","data-dxr-peer":t,"data-peer":t},[this.stage,E("div",{class:"dxr-call-talk"})]),e.o.ui||W(this.badge,!1),e.ui.grid.appendChild(this.el),this._renderBadge()}display(){return Ct(this.route)}info(){return Object.freeze({id:this.id,format:this.format||"mono",display:this.display(),state:this.conn,muted:this.remote.muted,cameraOff:this.remote.cameraOff,speaking:this.speaking})}diag(){return{...this.info(),route:this.route,rectified:!!(this.hello&&this.hello.rectified),hello:this.hello,quality:this.quality,convergencePx:this.conv.current,autoConverge:{disparityPx:this.conv.measuredPx,ms:this.autoStats.n?this.autoStats.ms/this.autoStats.n:null,readMs:this.autoStats.n?this.autoStats.readMs/this.autoStats.n:null,method:this.autoStats.method,via:this.autoStats.via},lift:this.lifted?{live:this.liftLive,native:!!(this.liftHandle&&this.liftHandle.native),priority:this.call.liftPool?this.call.liftPool.priority(this.id):null,state:this.liftHandle?this.liftHandle.state||null:"pending"}:null,element:this.el}}setStream(e){this.video.srcObject!==e&&(this.video.srcObject=e,this.audio.srcObject=e,this._resetAutoConverge()),this.video.play().catch(()=>{}),this.audio.play().catch(()=>{})}onChannelOpen(){clearTimeout(this.helloTimer),this.helloTimer=setTimeout(()=>{this.format||(this.format="mono",this._maybeRoute())},Kr)}setHello(e){clearTimeout(this.helloTimer),this.hello=e,this.conv.hello=e;let t=this.format!==e.format;this.format=e.format,this.call.log("hello",{peer:this.id,format:e.format,width:e.width,height:e.height,rectified:e.rectified}),t?this._maybeRoute():this._renderBadge()}setHint(e){this.hintGate(performance.now())&&(this.conv.subjectZmm=e.subjectZmm)}setRemoteState(e){this.remote=e,this._renderBadge(),this._renderPlate(),this._updateVisible()}setSpeaking(e){e!==this.speaking&&(this.speaking=e,this.el.classList.toggle("dxr-call-tile--speaking",e))}setConn(e){e==="unreachable"&&this.conn!=="unreachable"&&this.call.error("unreachable",`${this.call.t("unreachable")}. Still retrying in the background.`,Object.assign(new Error("unreachable"),{peer:this.id})),this.conn=e,e==="connected"&&this.leaveTimer&&(clearTimeout(this.leaveTimer),this.leaveTimer=null),this._renderPlate()}_renderPlate(){let e=this.call.t,t=this.conn==="left"?e("leftCall"):this.conn==="unreachable"?e("unreachable"):this.conn==="reconnecting"?e("reconnecting"):this.conn!=="connected"?e("connecting"):this.remote.cameraOff?e("cameraOffPlate"):null;this.plate.textContent=t||"",W(this.plate,!!t)}_renderBadge(){let e=this.call.t,t=this.route==="woven-sbs"?e("badge3D"):this.route==="lifted"?e("badge2D3D"):e("badge2D"),i=this.route?this.route==="lifted"&&!this.liftLive?`${t}${e("badgePending")}`:t:e("badgePending");this.badge.replaceChildren(E("b",{text:i})),this.badge.dataset.route=this.route||"",this.remote.muted&&this.badge.insertAdjacentHTML("beforeend",q.mutedSmall)}_maybeRoute(){!this.format||(this.video.readyState||0)<2||!this.video.videoWidth||this.reroute(!1)}reroute(e){let t=this.call,i=t.liftPool,r=this.forceFlat&&this.format==="sbs"?{route:"flat-left"}:Tt({format:this.format,woven:t.woven,mono3D:t.mono3DOn?"auto":"off",lift:!!i,overBudget:i?!i.canAcquire(this.id):!1,failed:this.liftFailed});this.format!=="sbs"&&t.woven&&t.mono3DOn&&!t._liftP&&t._ensureLift(),this.format!=="sbs"&&t.woven&&t.liftMissing&&t._warnLiftMissing();let s=`${r.route}|${this.format}`;!e&&s===this.routedKey||(this.routedKey=s,this._unregister(),this.route=r.route,r.route==="woven-sbs"?this._registerWoven():r.route==="lifted"&&this._registerLifted(),t.log("route",{peer:this.id,route:r.route,format:this.format,mono3d:r.mono3d||null}),t.emit("display",{id:this.id,display:this.display()}),t.listeners.get("format")?.size&&t.emit("format",{id:this.id,format:this.format,route:r.route,mono3d:r.mono3d||null,hello:this.hello}),this._renderBadge())}_registerWoven(){let e=this.call;this.convCanvas||(this.convCanvas=document.createElement("canvas")),this._paintConv(),W(this.cover,!0);let t=e.wall.addImage(this.canvas,this.convCanvas);this.handle=t,t.firstWoven?.then(i=>{this.handle===t&&(W(this.cover,!1),e.log("first-woven",{peer:this.id,woven:i.woven,reason:i.reason,ms:Math.round(i.ms)}),!i.woven&&i.reason==="layer-failed"&&this._layerFailed())})}_registerLifted(){let e=this.call,t=e.liftPool;this.lifted=!0,this.liftLive=!1,this.video.classList.add("dxr-call-liftsrc"),this.canvas.classList.add("dxr-call-liftflat"),this.video.parentNode!==this.stage&&this.stage.insertBefore(this.video,this.stage.firstChild),this._observeVisible(),t.acquire(this.id,this.video,{wall:e.wall,visible:this.visible,onError:i=>this._liftError(i)}).then(i=>{if(!i||!this.lifted||t.handle(this.id)!==i)return;this.liftHandle=i;let r=s=>{s==="live"?this._liftShowing(!0):(s==="error"||s==="disposed")&&this._liftShowing(!1)};this._liftOff=[i.on?.("statechange",s=>r(s&&s.state)),i.on?.("error",s=>{s&&s.fatal&&this._liftError(s.error)})],i.state==="live"?this._liftShowing(!0):i.canvas&&i.canvas.style&&(i.canvas.style.visibility="hidden"),e.log("lifted",{peer:this.id,native:!!i.native,woven:!!i.woven,state:i.state||null,provider:i.stats&&i.stats.provider||null})})}_liftShowing(e){if(e===this.liftLive)return;this.liftLive=e;let t=this.liftHandle;e?(t&&t.canvas&&t.canvas.style&&!t.native&&(t.canvas.style.visibility=""),this.canvas.style.visibility="hidden",this.liftFails=0,this.call.liftProven||(this.call.liftProven=!0,this.call._refreshLobby())):this.canvas.style.visibility="",this.call.log("lift-live",{peer:this.id,live:e}),this._renderBadge()}_liftError(e){this.lifted&&(this.call.log("lift-error",{peer:this.id,message:String(e&&e.message||e).slice(0,200)}),this.liftFailed=!0,this.reroute(!0),!(this.liftFails++>=es)&&(clearTimeout(this.liftTimer),this.liftTimer=setTimeout(()=>{this.liftFailed=!1,this.reroute(!1)},B(this.liftFails-1,{baseMs:3e3,maxMs:3e4}))))}_observeVisible(){this._io||typeof IntersectionObserver!="function"||(this._io=new IntersectionObserver(e=>{let t=e[e.length-1];this._onscreen=!!(t&&t.isIntersecting),this._updateVisible()}),this._io.observe(this.stage))}_updateVisible(){let e=this._onscreen!==!1&&!this.remote.cameraOff;e!==this.visible&&(this.visible=e,this.call.liftPool?.setVisible(this.id,e))}_layerFailed(){if(this.forceFlat=!0,this.reroute(!0),this.layerFails++>=Qr)return;let e=B(this.layerFails-1,{baseMs:1500,maxMs:2e4});this.call.log("layer-retry",{peer:this.id,attempt:this.layerFails,inMs:e}),clearTimeout(this.layerTimer),this.layerTimer=setTimeout(()=>{this.forceFlat=!1,this.call.woven&&this.reroute(!0)},e)}onWallLost(){this.handle=null,this.reroute(!0)}_unregister(){if(W(this.cover,!1),this.lifted){this.lifted=!1;for(let e of this._liftOff||[])typeof e=="function"&&e();this._liftOff=null,this.call.liftPool?.release(this.id),queueMicrotask(()=>this.call.state!=="left"&&this.call._rerouteMono()),this.liftHandle=null,this.liftLive=!1,this.canvas.style.visibility="",this.canvas.classList.remove("dxr-call-liftflat"),this._io&&(this._io.disconnect(),this._io=null),this.video.parentNode&&(this.video.remove(),this.video.classList.remove("dxr-call-liftsrc"),setTimeout(()=>this.video.srcObject&&this.video.play().catch(()=>{}),0))}if(this.handle){try{this.handle.remove()}catch{}this.handle=null}}paint(){this.route&&(this.route==="woven-sbs"?this._paintConv():this.route==="lifted"?this.liftLive||En(this.canvas,this.video):En(this.canvas,this.video,{eyeHalf:this.route==="flat-left"?0:null}))}_paintConv(){let e=this.video,t=e.videoWidth,i=e.videoHeight;if(!t||!i||(e.readyState||0)<2||!this.convCanvas)return;let r=t/2,s=this.call.o.tileAspect,{w:o,h:a}=be(r,i,s),l=this.convCanvas;(l.width!==2*o||l.height!==a)&&(l.width=2*o,l.height=a),this.call.o.autoConverge&&this._sampleDisparity(e,t,i);let c=this.conv.step(r),p=l.getContext("2d");for(let f of[0,1]){let h=X(r,i,s,c,f);p.drawImage(e,f*r+h.sx,h.sy,h.sw,h.sh,f*o,0,o,a)}}_sampleDisparity(e,t,i){let r=performance.now();if(this.autoPending||r-this.autoAt<ts)return;if(this.autoAt=r,typeof VideoFrame=="function"){let f=null;try{f=new VideoFrame(e)}catch{f=null}if(f&&is.has(f.format)){this.autoPending=!0;let h=this.autoGen,d=f.visibleRect?f.visibleRect.width:f.displayWidth,m=f.visibleRect?f.visibleRect.height:f.displayHeight,u=new Uint8Array(f.allocationSize());f.copyTo(u).then(v=>{if(h!==this.autoGen)return;let y=performance.now(),b=Math.max(1,Math.ceil(d/2/Mn)),C=Vi(u,v[0].offset,v[0].stride,d,m,b);this._applyMeasurement(C.img,C.w,C.h,C.w/d,r,performance.now()-y,"videoframe")}).catch(()=>{h===this.autoGen&&this._applyMeasurement(null,0,0,1,r,0,"videoframe")}).finally(()=>{f.close(),this.autoPending=!1});return}f&&f.close()}let s=Math.min(1,Mn/(t/2)),o=Math.max(2,Math.round(t*s/2)*2),a=Math.max(2,Math.round(i*s));this.autoCanvas||(this.autoCanvas=document.createElement("canvas"));let l=this.autoCanvas;(l.width!==o||l.height!==a)&&(l.width=o,l.height=a);let c=l.getContext("2d",{willReadFrequently:!0}),p=null;try{c.drawImage(e,0,0,o,a),p=Be(c.getImageData(0,0,o,a).data,o*a)}catch{p=null}this._applyMeasurement(p,o,a,o/t,r,performance.now()-r,"canvas")}_applyMeasurement(e,t,i,r,s,o,a){if(this.destroyed)return;let l=performance.now(),c=e?this.autoFocus.measure(e,t,i,s):null,p=this.autoTrack.push(c?c.d/r:null);this.conv.measuredPx=p,this.autoStats.n++,this.autoStats.readMs+=o,this.autoStats.ms+=o+(performance.now()-l),this.autoStats.method=c?c.method:null,this.autoStats.via=a,c&&!this.autoLocked&&(this.autoLocked=!0,this.call.log("auto-converge",{peer:this.id,disparityPx:Math.round(p*10)/10,at:{x:Math.round(c.x/r),y:Math.round(c.y/r)},ncc:Math.round(c.c*100)/100,method:c.method,via:a,ms:Math.round(o+(performance.now()-l))}))}_resetAutoConverge(){this.autoGen++,this.autoTrack.reset(),this.autoFocus.reset(),this.conv.measuredPx=null,this.autoLocked=!1}destroy(){this.destroyed=!0,this.autoGen++,clearTimeout(this.helloTimer),clearTimeout(this.layerTimer),clearTimeout(this.leaveTimer),clearTimeout(this.liftTimer),this._unregister(),this.video.srcObject=null,this.audio.srcObject=null,this.el.remove()}},ei=class{constructor(e,t){this.call=e,this.canvas=E("canvas"),this.badge=E("div",{class:"dxr-call-badge",part:"badge"}),this.plate=E("div",{class:"dxr-call-state dxr-call-hidden",part:"plate"}),this.stage=E("div",{class:"dxr-call-stage"},[this.canvas,this.badge,this.plate]),this.stage.style.aspectRatio=String(e.o.tileAspect),this.el=E("div",{class:"dxr-call-tile dxr-call-tile--self",part:"tile"},[this.stage,E("div",{class:"dxr-call-talk"})]),t.appendChild(this.el),this.view=null,this.cam=null}get route(){return this.view?this.view.route:null}update(){let e=this.call.local,t=this.call.t,i=!e||!e.videoTrack;this.plate.textContent=i?this.call.camStatus==="busy"?t("cameraBusy"):this.call.camStatus==="pending"?"":t("noCamera"):this.call.camOff?t("cameraOffPlate"):"",W(this.plate,i||this.call.camOff),this.reroute(!1)}reroute(e){let t=this.call.local,i=t&&t.videoTrack?t.cam:null,r=this.call.woven?this.call.wall:{supported:!1};if(!i||i.state!=="live")return this.detach(),this._badge();this.view&&this.cam===i?this.view._reroute(e,r):(this.detach(),this.cam=i,this.view=Ht(r,this.canvas,i,{mirror:!0,autoConverge:!1,aspect:this.call.o.tileAspect,onRouteChange:(s,o)=>{this.cam===i&&(this.call.log("self-route",{route:s,woven:o.woven,reason:o.reason}),this._badge())}})),this._badge()}_badge(){let e=this.call.t,t=!!(this.view&&this.view.woven);this.badge.replaceChildren(E("b",{text:`${e("you")} \xB7 ${e(t?"badge3D":"badge2D")}`})),this.badge.dataset.route=this.route||""}diag(){return this.view?this.view.weaveState():{route:null,woven:!1,reason:"no-camera",firstWoven:null,layerRetries:0}}onWallLost(){this.view?._onWallLost(),this._badge()}detach(){this.view&&this.view.remove(),this.view=null,this.cam=null}setSpeaking(e){this.el.classList.toggle("dxr-call-tile--speaking",e)}},rs="1.31",kn=new Set;function D(n,e,t){let i=()=>{kn.has(n)||(kn.add(n),console.warn(`${G} \`${n}\` is internal and leaves '@displayxr/inline3d/call' in ${rs} \u2014 import it from ${e} if you must, or stop depending on it`))};return typeof t=="function"?new Proxy(t,{apply(r,s,o){return i(),Reflect.apply(r,s,o)},construct(r,s){return i(),Reflect.construct(r,s)}}):t&&typeof t=="object"?new Proxy(t,{get(r,s,o){return typeof s=="string"&&i(),Reflect.get(r,s,o)}}):t}var co=D("normalizeCallOptions","js/call/options.js",Xt),ho=D("newRoomId","js/call/wire.js",xt),fo=D("isValidRoomId","js/call/wire.js",ce),uo=D("buildInviteLink","js/call/wire.js",He),po=D("normalizeHello","js/call/wire.js",St),mo=D("makeHello","js/call/wire.js",Mt),go=D("routeFor","js/call/wire.js",Tt),_o=D("badgeFor","js/call/wire.js",Ct),vo=D("createLiveGate","js/call/wire.js",Rt),yo=D("convergenceShiftPx","js/camera/converge.js",je),wo=D("lowPass","js/camera/converge.js",Ne),bo=D("clampShift","js/camera/converge.js",We),xo=D("eyeCropRect","js/camera/geometry.js",X),So=D("mirrorSwapOps","js/camera/geometry.js",ae),Mo=D("mirrorSwapPixels","js/camera/geometry.js",yt),Eo=D("maxBitrateKbps","js/call/wire.js",Ve),ko=D("measureFocusDisparity","js/camera/disparity.js",Ot),To=D("preferVideoCodecs","js/call/sdp.js",Ee),Co=D("sortCodecCapabilities","js/call/sdp.js",$e),Ro=D("VIDEO_CODEC_ORDER","js/call/sdp.js",Me),Do=D("MeshTransport","js/call/transport.js",ke),Lo=D("clampMaxPeers","js/call/transport.js",Te),Ao=D("qrEncode","js/call/qr.js",Ut),Oo=D("roomKey","js/call/signaling.js",Bt);var Io=D("PLATE_TEXT","js/call/ui.js (CALL_STRINGS)",Object.freeze({unreachable:De.unreachable,cameraBusy:De.cameraBusy})),Po=D("CALL_ACCENTS","js/call/ui.js",qt),Fo=D("normalizeMono3D","js/call/lift.js",ye),jo=D("resolveLift","js/call/lift.js",nt),Wo=D("createLiftPool","js/call/lift.js",ot),No=D("createFrameWatch","js/call/lift.js",st),zo=D("liftConvergenceFor","js/call/lift.js",ve),Ho=D("liftPriorityFor","js/call/lift.js",Le),Vo=D("setLiftPriority","js/call/lift.js",rt),$o=D("defaultLiftSpecifier","js/call/lift.js",it),Uo=D("LIFT_PRIORITY","js/call/lift.js",_e);et();ii(()=>new URL("./lift.js",import.meta.url).href);export{Jt as CALL_EVENT_PREFIX,on as CAMERA_SDK,Qe as DXR_SIGNAL_DEFAULT,pe as DxrCallElement,Tn as addCall,Ht as addCameraView,Kt as attrsToOpts,Ti as createInline3D,et as defineCallElement,fe as dxrSignaling,Ei as inline3DAvailable,Ze as isStereoCamera,Yt as mountCall,zt as openCamera,Se as parseInviteLink,Pt as parseStereoXmp,Ji as readJpegStereoMeta,Ft as readJpegXmp,nn as readWebmStereoMeta,Fe as sharedInline3D,Ye as suggestedName};
|
package/js/inline3d-call.js
CHANGED
|
@@ -1127,6 +1127,9 @@ class Call {
|
|
|
1127
1127
|
hello: this.hello(),
|
|
1128
1128
|
transport: this.transport,
|
|
1129
1129
|
peers: [...this.tiles.values()].map((tile) => tile.diag()),
|
|
1130
|
+
// The self view's ACTUAL weave state (web#131): route, woven, the fallback reason and the
|
|
1131
|
+
// tile's firstWoven result — null without a self view.
|
|
1132
|
+
self: this.self ? this.self.diag() : null,
|
|
1130
1133
|
mono3D: { ...this._mono3DInfo(), lift: this.liftApi, pool: this.liftPool ? this.liftPool.list() : [] },
|
|
1131
1134
|
speaker: this.speakerId,
|
|
1132
1135
|
depth: this.depth,
|
|
@@ -1866,14 +1869,34 @@ class SelfTile {
|
|
|
1866
1869
|
else {
|
|
1867
1870
|
this.detach();
|
|
1868
1871
|
this.cam = cam;
|
|
1869
|
-
|
|
1872
|
+
// onRouteChange: the view drops to its flat left eye by itself when the wall says the tile
|
|
1873
|
+
// will not weave (firstWoven → woven:false, web#131), and the badge must follow it.
|
|
1874
|
+
this.view = addCameraView(wall, this.canvas, cam, {
|
|
1875
|
+
mirror: true,
|
|
1876
|
+
autoConverge: false,
|
|
1877
|
+
aspect: this.call.o.tileAspect,
|
|
1878
|
+
onRouteChange: (route, st) => {
|
|
1879
|
+
if (this.cam !== cam) return; // a view this tile already replaced
|
|
1880
|
+
this.call.log('self-route', { route, woven: st.woven, reason: st.reason });
|
|
1881
|
+
this._badge();
|
|
1882
|
+
},
|
|
1883
|
+
});
|
|
1870
1884
|
}
|
|
1871
1885
|
this._badge();
|
|
1872
1886
|
}
|
|
1873
1887
|
|
|
1888
|
+
/** 3D only while the view is on the woven route — a layer the wall failed has already taken it flat. */
|
|
1874
1889
|
_badge() {
|
|
1875
1890
|
const t = this.call.t;
|
|
1876
|
-
|
|
1891
|
+
const woven = !!(this.view && this.view.woven);
|
|
1892
|
+
this.badge.replaceChildren(el('b', { text: `${t('you')} · ${woven ? t('badge3D') : t('badge2D')}` }));
|
|
1893
|
+
this.badge.dataset.route = this.route || '';
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
/** For `call.diagnostics().self`: what the self view actually shows. */
|
|
1897
|
+
diag() {
|
|
1898
|
+
if (!this.view) return { route: null, woven: false, reason: 'no-camera', firstWoven: null, layerRetries: 0 };
|
|
1899
|
+
return this.view.weaveState();
|
|
1877
1900
|
}
|
|
1878
1901
|
|
|
1879
1902
|
onWallLost() {
|
package/js/inline3d-camera.js
CHANGED
|
@@ -51,6 +51,11 @@ export const CAMERA_SDK = 'inline3d-camera/1';
|
|
|
51
51
|
const AUTO_CONV_INTERVAL_MS = 200;
|
|
52
52
|
const AUTO_CONV_EYE_WIDTH = 240;
|
|
53
53
|
const FRAME_WAIT_MS = 4000;
|
|
54
|
+
// A self view whose layer the wall could not build (`firstWoven` → `woven:false, 'layer-failed'`)
|
|
55
|
+
// goes flat and re-registers a few times with backoff — the remote tile's rule (web#131).
|
|
56
|
+
const LAYER_RETRIES = 4;
|
|
57
|
+
const LAYER_RETRY_BASE_MS = 1500;
|
|
58
|
+
const LAYER_RETRY_MAX_MS = 20000;
|
|
54
59
|
const RECORD_MIME_CANDIDATES = ['video/webm;codecs=vp9', 'video/webm;codecs=vp8', 'video/webm', 'video/mp4'];
|
|
55
60
|
|
|
56
61
|
const hasDoc = () => typeof document !== 'undefined' && document && typeof document.createElement === 'function';
|
|
@@ -471,7 +476,12 @@ function sizeFlat(canvas) {
|
|
|
471
476
|
* @param {object|null} wall a `createInline3D()` / `sharedInline3D()` result (may be unsupported) or null
|
|
472
477
|
* @param {HTMLCanvasElement} canvas the tile — its CSS box is the shape the viewer sees
|
|
473
478
|
* @param {StereoCamera} cam
|
|
474
|
-
*
|
|
479
|
+
* On a 3D wall the view follows its tile's `firstWoven`: a window the wall will not weave
|
|
480
|
+
* (`'layer-failed'`, `'session-ended'`) drops the view to the flat left eye — never the packed
|
|
481
|
+
* pair — with `fallbackReason` saying why, and `onRouteChange(route, state)` tells the page (a
|
|
482
|
+
* badge reads `route`). A refused layer is retried a few times; `_reroute(true, wall)` recovers.
|
|
483
|
+
*
|
|
484
|
+
* @param {{ mirror?: boolean, autoConverge?: boolean, depth?: number, aspect?: number, onRouteChange?: Function }} [opts]
|
|
475
485
|
*/
|
|
476
486
|
export function addCameraView(wall, canvas, cam, opts = {}) {
|
|
477
487
|
if (!canvas || typeof canvas.getContext !== 'function') throw new TypeError(`${TAG} addCameraView(wall, canvas, cam, opts) needs a canvas`);
|
|
@@ -494,6 +504,15 @@ class CameraView {
|
|
|
494
504
|
this.setDepth(o.depth);
|
|
495
505
|
this.route = null;
|
|
496
506
|
this.handle = null;
|
|
507
|
+
// Why a pair on a 3D-capable wall is shown FLAT (web#131): the wall said this tile's window
|
|
508
|
+
// will not weave (`firstWoven` → woven:false — 'layer-failed', 'session-ended'). Null while
|
|
509
|
+
// nothing has failed. A packed pair is never the visible fallback: the view paints one eye.
|
|
510
|
+
this.fallbackReason = null;
|
|
511
|
+
// The current registration's settled `firstWoven`, null while pending / not registered.
|
|
512
|
+
this._fw = null;
|
|
513
|
+
this._onRouteChange = typeof o.onRouteChange === 'function' ? o.onRouteChange : null;
|
|
514
|
+
this._layerFails = 0;
|
|
515
|
+
this._layerTimer = 0;
|
|
497
516
|
this.buffer = null; // the SBS canvas the wall repaints the tile from (woven route)
|
|
498
517
|
this.removed = false;
|
|
499
518
|
this._raf = 0;
|
|
@@ -507,11 +526,30 @@ class CameraView {
|
|
|
507
526
|
if (this._loop) this._start();
|
|
508
527
|
}
|
|
509
528
|
|
|
510
|
-
/**
|
|
529
|
+
/**
|
|
530
|
+
* True while the view is on the woven route: registered on a 3D wall, and the wall has not said
|
|
531
|
+
* the tile will not weave (a failed layer drops the view to `'flat-left'`). Route is
|
|
532
|
+
* `'woven-sbs'` (3D on the panel) | `'flat-left'` (a pair, shown flat) | `'flat'` (mono).
|
|
533
|
+
*/
|
|
511
534
|
get woven() {
|
|
512
535
|
return this.route === 'woven-sbs';
|
|
513
536
|
}
|
|
514
537
|
|
|
538
|
+
/**
|
|
539
|
+
* What is actually on the panel, for diagnostics: `{ route, woven, reason, firstWoven,
|
|
540
|
+
* layerRetries }`. `firstWoven` is the current registration's settled result, `'pending'`
|
|
541
|
+
* before it settles, null off the woven route.
|
|
542
|
+
*/
|
|
543
|
+
weaveState() {
|
|
544
|
+
return {
|
|
545
|
+
route: this.route,
|
|
546
|
+
woven: this.woven,
|
|
547
|
+
reason: this.fallbackReason,
|
|
548
|
+
firstWoven: this.route === 'woven-sbs' ? (this._fw ? { ...this._fw } : 'pending') : null,
|
|
549
|
+
layerRetries: this._layerFails,
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
|
|
515
553
|
/** The per-eye convergence shift currently painted, source px. */
|
|
516
554
|
get convergencePx() {
|
|
517
555
|
return this.conv.current;
|
|
@@ -543,20 +581,77 @@ class CameraView {
|
|
|
543
581
|
return this.autoConverge;
|
|
544
582
|
}
|
|
545
583
|
|
|
546
|
-
/**
|
|
584
|
+
/**
|
|
585
|
+
* Re-register on the wall (the call does this when the weave goes live, #172, or a session is
|
|
586
|
+
* recovered). A FORCED reroute also clears a layer fallback (web#131): a wall that came back
|
|
587
|
+
* gets a fresh registration. An unforced one keeps the view flat while a fallback stands.
|
|
588
|
+
*/
|
|
547
589
|
_reroute(force, wall) {
|
|
548
590
|
if (wall !== undefined) this.wall = wall;
|
|
549
591
|
if (this.removed) return;
|
|
592
|
+
if (force && this.fallbackReason) {
|
|
593
|
+
this.fallbackReason = null;
|
|
594
|
+
clearTimeout(this._layerTimer);
|
|
595
|
+
this._layerTimer = 0;
|
|
596
|
+
}
|
|
550
597
|
const cam = this.cam;
|
|
551
598
|
const live = cam.state === 'live' && cam.video;
|
|
552
|
-
const
|
|
599
|
+
const wovenOk = cam.format === 'sbs' && live && this.wall && this.wall.supported && !this.fallbackReason;
|
|
600
|
+
const route = wovenOk ? 'woven-sbs' : cam.format === 'sbs' ? 'flat-left' : 'flat';
|
|
553
601
|
if (!force && route === this.route) return;
|
|
602
|
+
const prev = this.route;
|
|
554
603
|
this._unregister();
|
|
555
604
|
this.route = route;
|
|
556
|
-
if (route === 'woven-sbs')
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
605
|
+
if (route === 'woven-sbs') this._registerWoven();
|
|
606
|
+
if (route !== prev) this._routeChanged();
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
_registerWoven() {
|
|
610
|
+
if (!this.buffer) this.buffer = document.createElement('canvas');
|
|
611
|
+
this._paintWoven(); // the first frame exists before the layer does
|
|
612
|
+
const handle = this.wall.addImage(this.canvas, this.buffer);
|
|
613
|
+
this.handle = handle;
|
|
614
|
+
this._fw = null;
|
|
615
|
+
const fw = handle && handle.firstWoven;
|
|
616
|
+
if (!fw || typeof fw.then !== 'function') return;
|
|
617
|
+
fw.then((res) => {
|
|
618
|
+
// A result for a registration we already left (removed, re-registered) says nothing now.
|
|
619
|
+
if (this.handle !== handle || this.removed || !res) return;
|
|
620
|
+
this._fw = { woven: !!res.woven, confirmed: !!res.confirmed, reason: res.reason || null, ms: res.ms };
|
|
621
|
+
this.cam.log?.('view-first-woven', { woven: !!res.woven, reason: res.reason || null });
|
|
622
|
+
if (res.woven) {
|
|
623
|
+
this._layerFails = 0;
|
|
624
|
+
this._routeChanged(); // the state settled; the route did not move
|
|
625
|
+
} else if (res.reason !== 'removed') this._layerLost(res.reason || 'layer-failed');
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* The wall said this window will not weave (web#131): the canvas must never be left showing the
|
|
631
|
+
* packed pair under a 3D badge. Go flat (one eye, mirrored) and say why. A layer the browser
|
|
632
|
+
* refused is retried a few times with backoff while the wall stays up (the remote tile's rule);
|
|
633
|
+
* a session that ended waits for `_reroute(true, wall)` with the new wall.
|
|
634
|
+
*/
|
|
635
|
+
_layerLost(reason) {
|
|
636
|
+
this.fallbackReason = reason;
|
|
637
|
+
this._reroute(false);
|
|
638
|
+
if (reason !== 'layer-failed' || this._layerFails >= LAYER_RETRIES) return;
|
|
639
|
+
const delay = Math.min(LAYER_RETRY_MAX_MS, LAYER_RETRY_BASE_MS * Math.pow(2, this._layerFails++));
|
|
640
|
+
this.cam.log?.('view-layer-retry', { attempt: this._layerFails, inMs: delay });
|
|
641
|
+
clearTimeout(this._layerTimer);
|
|
642
|
+
this._layerTimer = setTimeout(() => {
|
|
643
|
+
this._layerTimer = 0;
|
|
644
|
+
if (this.removed || this.fallbackReason !== reason) return;
|
|
645
|
+
this._reroute(true);
|
|
646
|
+
}, delay);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
_routeChanged() {
|
|
650
|
+
if (!this._onRouteChange) return;
|
|
651
|
+
try {
|
|
652
|
+
this._onRouteChange(this.route, this.weaveState());
|
|
653
|
+
} catch (err) {
|
|
654
|
+
console.error(`${TAG} onRouteChange threw`, err);
|
|
560
655
|
}
|
|
561
656
|
}
|
|
562
657
|
|
|
@@ -672,6 +767,8 @@ class CameraView {
|
|
|
672
767
|
this.removed = true;
|
|
673
768
|
if (this._raf) cancelAnimationFrame(this._raf);
|
|
674
769
|
this._raf = 0;
|
|
770
|
+
clearTimeout(this._layerTimer);
|
|
771
|
+
this._layerTimer = 0;
|
|
675
772
|
this._unregister();
|
|
676
773
|
this.cam._views?.delete(this);
|
|
677
774
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@displayxr/inline3d",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.35.0",
|
|
4
4
|
"description": "Turn any HTML <canvas> into a 3D window on a spatial display, inside an ordinary web page, for the DisplayXR Browser. Dependency-free; progressive enhancement (falls back to plain 2D everywhere else).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.d.ts",
|