@displayxr/inline3d 1.27.0 → 1.29.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 +224 -0
- package/README.md +6 -3
- package/call-full.d.ts +21 -0
- package/call.d.ts +454 -0
- package/dist/call.js +81 -0
- package/index.d.ts +34 -2
- package/js/call/capture.js +212 -0
- package/js/call/disparity.js +432 -0
- package/js/call/element.js +217 -0
- package/js/call/lift.js +323 -0
- package/js/call/qr.js +283 -0
- package/js/call/sdp.js +86 -0
- package/js/call/signaling.js +203 -0
- package/js/call/transport.js +589 -0
- package/js/call/ui.js +146 -0
- package/js/call/wire.js +434 -0
- package/js/inline3d-buffer-limit.js +198 -0
- package/js/inline3d-call-full.js +48 -0
- package/js/inline3d-call.js +1901 -0
- package/js/inline3d-model-playcanvas.js +6 -0
- package/js/inline3d-model.js +6 -0
- package/js/inline3d-player.js +649 -218
- package/js/inline3d-splat-playcanvas.js +134 -18
- package/js/inline3d-splat-video.js +328 -29
- package/js/inline3d-splat.js +5 -0
- package/js/inline3d-viewer.js +86 -10
- package/js/inline3d.js +257 -15
- package/js/lift/index.js +15 -0
- package/model.d.ts +10 -1
- package/package.json +29 -4
- package/player.d.ts +49 -4
- package/splat.d.ts +52 -3
- package/viewer.d.ts +12 -1
package/dist/call.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* @displayxr/inline3d 1.29.0 — dist/call.js — Apache-2.0 — https://github.com/DisplayXR/displayxr-web */
|
|
2
|
+
var _e=Object.freeze({speaker:"high",other:"normal",hidden:"paused"}),mi=["high","normal","low","paused"],gi=.02,_i=1e3/20,vi=3e3,yi=1e3/28;function ye(s){return typeof s=="function"?s:s===!1||s==="off"?"off":"auto"}function bi(s=import.meta.url){return ee?typeof ee=="function"?ee():ee:new URL("../lift/index.js",s).href}var ee=null;function tt(s){ee=s||null}function wi(){return import(bi())}async function it(s,{importer:e=wi,nav:t=globalThis.navigator,log:i=null,capsOpts:n={webFallback:!0}}={}){let r=(h,d)=>i&&i(h,d),o=(h,d={})=>(r("lift-unavailable",{reason:h,...d}),{lift:null,capabilities:null,caps:null,source:"none",reason:h}),a=ye(s);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 m=typeof l.liftCapabilities=="function"?l.liftCapabilities:null,f=null;if(m){try{f=await m(n)}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 r("lift-ready",{native:!!(f&&f.native),provider:f&&f.provider||null}),{lift:c,capabilities:m,caps:f,source:"module",reason:null}}function ve(s){let e=Number.isFinite(+s)&&s!==null?Math.max(-1,Math.min(1,+s)):0;return Math.abs(e)<gi?"auto":Math.round((.5+.5*e)*1e3)/1e3}function et({id:s,speakerId:e,visible:t=!0}){return t?s!=null&&s===e?_e.speaker:_e.other:_e.hidden}function xi(s,e){if(!s||!mi.includes(e)||typeof s.setPriority!="function")return!1;try{return s.setPriority(e)!==!1}catch{return!1}}function nt({degradedMs:s=_i,recoveredMs:e=yi,holdMs:t=vi,alpha:i=.1}={}){let n=null,r=0,o=!1;return{feed(a){if(!(a>0)||a>1e3)return null;if(n=n===null?a:n+i*(a-n),o){if(n<e)return o=!1,r=0,"recovered"}else if(r=n>s?r+a:0,r>=t)return o=!0,"degraded";return null},reset(){n=null,r=0,o=!1},get frameMs(){return n},get degraded(){return o}}}function st({lift:s,max:e=4,log:t=null,options:i=null}={}){let n=i&&typeof i=="object"?i:{},r=new Map,o=null,a=0,l=0,c=(h,d)=>t&&t(h,d),m=(h,d)=>{if(!d.handle)return;let u=et({id:h,speakerId:o,visible:d.visible});if(u===d.priority)return;d.priority=u;let p=xi(d.handle,u);c("lift-priority",{peer:h,priority:u,applied:p})},f={get size(){return r.size},get max(){return e},set max(h){e=Math.max(0,h|0)},has:h=>r.has(h),handle:h=>r.get(h)&&r.get(h).handle||null,priority:h=>r.get(h)&&r.get(h).priority||null,canAcquire:h=>r.has(h)||r.size<e,acquire(h,d,{wall:u,visible:p=!0,onError:_}={}){let b=r.get(h);if(b)return b.pending||Promise.resolve(b.handle);if(r.size>=e)return Promise.resolve(null);let x=++l,k=et({id:h,speakerId:o,visible:p}),w={gen:x,handle:null,visible:p,priority:k,pending:null};r.set(h,w);let I={quality:"auto",...n,mode:"live",wall:u,ui:"none",convergence:ve(a),priority:k};return c("lift-acquire",{peer:h,priority:k,convergence:I.convergence}),w.pending=Promise.resolve().then(()=>s(d,I)).then(E=>{if(r.get(h)!==w||w.gen!==x){try{E&&E.remove&&E.remove()}catch{}return null}return w.pending=null,w.handle=E||null,w.priority=null,m(h,w),E&&typeof E.setConvergence=="function"&&E.setConvergence(ve(a)),w.handle},E=>(r.get(h)===w&&r.delete(h),c("lift-failed",{peer:h,message:String(E&&E.message||E).slice(0,200)}),_&&_(E),null)),w.pending},release(h){let d=r.get(h);if(d){if(r.delete(h),d.handle)try{d.handle.remove()}catch{}c("lift-release",{peer:h})}},releaseAll(){for(let h of[...r.keys()])f.release(h)},setSpeaker(h){o=h===void 0?null:h;for(let[d,u]of r)m(d,u)},setVisible(h,d){let u=r.get(h);!u||u.visible===!!d||(u.visible=!!d,m(h,u))},setDepth(h){a=h;let d=ve(h);for(let u of r.values())u.handle&&typeof u.handle.setConvergence=="function"&&u.handle.setConvergence(d);return d},get anyWeb(){for(let h of r.values())if(h.handle&&!h.handle.native)return!0;return!1},list(){return[...r].map(([h,d])=>({id:h,priority:d.priority,pending:!!d.pending,native:!!(d.handle&&d.handle.native)}))}};return f}var Si=null;function rt(s){Si=typeof s=="function"?s:null}var ot=new WeakMap,z;function at(s){let e=null;for(let[t,i]of s)i>0&&(!e||i<e[1])&&(e=[t,i]);return e}function Mi(s){if(!s||typeof s.getParameter!="function")return null;let e=ot.get(s);if(e)return e;let t,i,n;try{t=s.getParameter(s.MAX_TEXTURE_SIZE??3379),i=s.getParameter(s.MAX_RENDERBUFFER_SIZE??34024),n=s.getParameter(s.MAX_VIEWPORT_DIMS??3386)}catch{return null}let r=n&&n.length>=2?n[0]:0,o=n&&n.length>=2?n[1]:0,a=at([["MAX_TEXTURE_SIZE",t],["MAX_RENDERBUFFER_SIZE",i],["MAX_VIEWPORT_DIMS",r]]),l=at([["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 ot.set(s,c),c}function lt(){if(z!==void 0)return z;z=null;try{if(typeof document>"u"||!document||typeof document.createElement!="function")return z;let s=document.createElement("canvas"),e=s.getContext("webgl2")||s.getContext("webgl");if(!e)return z;z=Mi(e),e.getExtension?.("WEBGL_lose_context")?.loseContext?.()}catch{z=null}return z}function ct(s,e,t,{cols:i=2,rows:n=1}={}){let r=s*i,o=e*n,a={eyeW:s,eyeH:e,cols:i,scale:1,clamped:!1,reqW:r,reqH:o,bufW:r,bufH:o,limitName:"",limitValue:0};if(!t||!(s>0)||!(e>0))return a;let l=t.maxW/r,c=t.maxH/o,m=Math.min(l,c);if(!(m<1))return a;let f=l<=c,h=Math.max(1,Math.min(Math.floor(s*m+1e-9),Math.floor(t.maxW/i))),d=Math.max(1,Math.min(Math.floor(e*m+1e-9),Math.floor(t.maxH/n)));return{eyeW:h,eyeH:d,cols:i,scale:m,clamped:!0,reqW:r,reqH:o,bufW:h*i,bufH:d*n,limitName:f?t.nameW:t.nameH,limitValue:f?t.valueW:t.valueH}}function be(s){return Math.round(s*1e3)/1e3}function ht(s,e,t){let i=typeof t=="number"?` (renderScale ${be(t)} \u2192 ${be(t*e.scale)})`:` (scale ${be(e.scale)})`;return`${s} ${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 dt(s,e){let t=s?.width||0,i=s?.height||0,n=e&&e.drawingBufferWidth>0?e.drawingBufferWidth:t,r=e&&e.drawingBufferHeight>0?e.drawingBufferHeight:i,o=t>0?n/t:1,a=i>0?r/i:1;return{sx:o,sy:a,w:n,h:r,mismatch:o!==1||a!==1}}function ft(s,e,t,i="laying the eyes out from the drawing buffer. Lower renderScale to stay inside the device limit."){return`${s} 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 q="smoothstep",xe=["linear","smoothstep","easeoutcubic"];function Se(s){if(typeof s!="string")return null;let e=s.toLowerCase().replace(/[-_\s]/g,"");return xe.includes(e)?e:null}function ki(s,e){if(e<=0)return 0;if(e>=1)return 1;if(s==="linear")return e;if(s==="easeoutcubic"){let t=1-e;return 1-t*t*t}return e*e*(3-2*e)}var j="idle",ut="rampDownThenFire",we="fireThenRampUp",re=class{constructor(e,t){this._phase=j,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=q,(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=Se(t)||q),this}get durationS(){return this._dur}get easing(){return this._easing}request({targetMode:e=null,targetViewCount:t,currentMode:i=null,currentViewCount:n,current:r,steady:o=1}={}){let a=!(t>1),l=!(n>1),c=Number.isFinite(o)?o:1,m=Number.isFinite(r)?r:c;return this._targetMode=e,this._from=m,a&&!l?(this._phase=ut,this._to=0,this._fireAtEnd=!0,this._firePending=!1):!a&&l?(this._phase=we,this._from=0,this._to=c,this._firePending=!0,this._fireAtEnd=!1):(this._phase=we,this._to=a?m: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!==j){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)*ki(this._easing,this._t),this._phase===we?(this._firePending&&(this._firePending=!1,t=!0),this._t>=1&&(this._phase=j)):this._t>=1&&(this._fireAtEnd&&(this._fireAtEnd=!1,t=!0),this._phase=j)}return{factor:this._cur,fire:t,mode:this._targetMode}}active(){return this._phase!==j}value(){return this._cur}firePending(){return this._phase===ut?this._fireAtEnd:this._firePending}cancel(){return this._phase=j,this._firePending=!1,this._fireAtEnd=!1,this._t=1,this}};var N=null;rt(s=>{let e=N;if(!e||!e._running||!s)return null;let t=i=>({layer:i.layer,session:e.session});for(let i of e._windows.values())if(i.canvas===s&&i.layer)return t(i);for(let i of e._windows.values())if(i.layer&&typeof s.contains=="function"&&s.contains(i.canvas))return t(i);for(let i of e._windows.values()){let n=i.canvas.parentElement;if(i.layer&&n&&typeof n.contains=="function"&&n.contains(s))return t(i)}return null});var Ei=()=>typeof navigator<"u"&&!!navigator.xr,$=()=>typeof window<"u"&&typeof window.XRDisplayLayer=="function",oe=()=>$()&&"excludeElement"in window.XRDisplayLayer.prototype,Me=()=>{if(!$())return!1;try{return"setViewRig"in window.XRDisplayLayer.prototype}catch{return!1}},Ci=["getDisplayInfo","getRenderingModes","requestRenderingMode"],St=["renderingmodechange","hardwaredisplaystatechange"],Re="trackingstatechange",Mt=["unknown","tracking","searching"],mt=[...St,Re];function ae(s){try{let e=s?s.trackingState:void 0;return Mt.includes(e)?e:null}catch{return null}}var ke=()=>{if(!$())return!1;try{let s=window.XRDisplayLayer.prototype;return Ci.every(e=>typeof s[e]=="function")}catch{return!1}},Ee=()=>{if(!$())return!1;try{return typeof window.XRDisplayLayer.prototype.undock=="function"}catch{return!1}},X=null;function G(){if(X!==null)return X;if(!$())return!1;try{let s=window.XRDisplayLayer.occlusionByDrawOrder;if(typeof s=="boolean")return X=s}catch{}return!1}function Ti(s){if(X!==null)return X;if(!s||!$()||!("occlusionByDrawOrder"in window.XRDisplayLayer.prototype))return null;try{return X=!!s.occlusionByDrawOrder}catch{return null}}var gt=!1;function Ce(){gt||(gt=!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 kt(){return Ei()&&$()}function Te(s){return{type:"display",position:{x:0,y:0,z:0},orientation:{x:0,y:0,z:0,w:1},virtualDisplayHeight:s.virtualDisplayHeight>0?s.virtualDisplayHeight:.24,ipdFactor:1,parallaxFactor:1,perspectiveFactor:1}}function Ri(s,e){let t=Number.isFinite(s.ipdFactor)?s.ipdFactor:1,i=Number.isFinite(s.parallaxFactor)?s.parallaxFactor:1;return{...s,ipdFactor:t*e,parallaxFactor:i*e}}var Di=16;function P(){return typeof performance<"u"&&performance&&typeof performance.now=="function"?performance.now():Date.now()}var Li=1200,_t=!1;function Ii(s){if(s==null)return q;let e=Se(s);return e||(_t||(_t=!0,console.warn(`[inline3d] createInline3D({ modeSwitch: { easing: ${JSON.stringify(s)} } }) is not a curve this SDK knows (${xe.join(" / ")}); using '${q}'.`)),q)}var vt=!1;function Oi(){vt||(vt=!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 De(s){return s&&s.detail!==void 0&&s.detail!==null?s.detail:void 0}function Et(s){let e=De(s);return e!==void 0?[e,s]:[s]}function Ai(s){for(let e of Et(s)){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 Pi(s){for(let e of Et(s)){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 yt=!1;function Fi(){yt||(yt=!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 bt=!1;function Wi(){bt||(bt=!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 Ct(s={}){let{referenceSpace:e="viewer",lazy:t=!0,rootMargin:i="50% 0px",autoChrome:n=!0,modeSwitch:r=null,untrackedFallback:o="none"}=s;if(!kt())return{supported:!1,trackingState:"unknown"};let a;try{a=await navigator.xr.requestSession("inline-3d")}catch(c){return{supported:!1,trackingState:"unknown",error:c}}let l=null;try{l=await a.requestReferenceSpace(e)}catch{}return new Le(a,l,{lazy:t,rootMargin:i,autoChrome:n,modeSwitch:r,untrackedFallback:o})}var te=null;function ce(s={}){return N&&N._running?Promise.resolve(N):te||(te=Ct(s).finally(()=>{te=null}),te)}var wt=.7,Ni=new Set(["IMG","SVG","VIDEO","CANVAS","BUTTON","INPUT","SELECT","TEXTAREA"]);function Hi(s){let e=[],t=document.createTreeWalker(s,NodeFilter.SHOW_ELEMENT);for(let i=t.nextNode();i;i=t.nextNode())if(!i.closest("[data-inline3d-no-overlay]")){if(Ni.has(i.tagName.toUpperCase())){e.push(i);continue}for(let n of i.childNodes)if(n.nodeType===Node.TEXT_NODE&&n.nodeValue.trim()){e.push(i);break}}return e}var Vi=4;function xt(s){let e=typeof window<"u"&&window.devicePixelRatio||1;return`${s.clientWidth}x${s.clientHeight}@${e}`}var Le=class{constructor(e,t,{lazy:i,rootMargin:n,autoChrome:r=!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=r,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 re((Number.isFinite(l.durationMs)?Math.max(0,l.durationMs):180)/1e3,Ii(l.easing)),this._stereoFactor=1,this._msFire=null,this._msArmedUp=!1,this._msLastMs=null,this._msTick=null,this._trackingSupported=ae(e)!==null,this._trackingState=this._trackingSupported?ae(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=Ee()?{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:n}):null,this._loopId=0,this._framePending=!1,this._frameCount=0,this._frameWatchdog=null,this._suspended=null,N&&N._running&&N!==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."),N=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))){G()&&Ce(),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(G()||!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,n=t.querySelectorAll(":scope > *, :scope > * > *, :scope > * > * > *");for(let r of n){if(r.closest("[data-inline3d-no-overlay]"))continue;let o=getComputedStyle(r).position;if(o!=="fixed"&&o!=="sticky")continue;let a=!1;for(let l of this._windows.keys())if(r===l||r.contains(l)){a=!0;break}if(!a){i.add(r);for(let l of Hi(r))i.add(l)}}for(let r of this._autoChromeEls){let o=!1;if(r.isConnected){for(let a of this._windows.keys())if(r===a||r.contains(a)){o=!0;break}}(!r.isConnected||o)&&(this._autoChromeEls.delete(r),this.removeGlobalOverlay(r))}for(let r of i)this._globalOverlays.has(r)||(this._autoChromeEls.add(r),this.addGlobalOverlay(r))}addImage(e,t,i={}){let n=this._register(e,"image",i);return n.ready=$i(t).then(r=>{n.img=r,n.repaint()}),this._handle(e,n)}addVideo(e,t,i={}){let n=this._register(e,"video",i);return n.video=t,this._handle(e,n)}addScene(e,t,i={}){i.viewRig&&i.virtualDisplayHeight!==void 0&&Wi();let n=this._register(e,"scene",{virtualDisplayHeight:.24,...i});return n.onFrame=t,n.ownsBuffer=!1,this._handle(e,n)}_handle(e,t){let i=this;return{remove:()=>this._remove(e),exclude:n=>{n&&(G()&&Ce(),t.excluded.add(n),this._applyExclusion(t,n))},unexclude:n=>{!n||!t.excluded.delete(n)||this._dropExclusion(t,n)},get trackingState(){return i._trackingState},setViewRig:n=>(t.viewRig=n||null,this._pushViewRig(t)),getDisplayInfo:()=>this._layerCall(t,"getDisplayInfo","getDisplayInfo()"),getRenderingModes:()=>this._getRenderingModes(t),requestRenderingMode:n=>this._requestRenderingModeEased(n,t),setStereoEnabled:n=>this._setStereoEnabled(n,t),on:(n,r)=>this.on(n,r),off:(n,r)=>this.off(n,r),onDisplayModeChange:n=>this._onDisplayModeChange(n),stats:()=>({frames:t.frames,monoFrames:t.monoFrames}),get firstWoven(){return t.fwPromise},onFirstWoven:n=>{if(typeof n!="function")throw new TypeError("[inline3d] onFirstWoven() takes a function.");let r=!0;return t.fwPromise.then(o=>{if(r)try{n(o)}catch(a){console.error("[inline3d] onFirstWoven callback threw",a)}}),()=>{r=!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?Te(e):null):(e.viewRig||(e.stereoSynthRig=!0),Ri(e.viewRig||Te(e),this._stereoFactor))}_setStereoCollapsed(e){let t=!!e;if(this._stereoCollapsed!==t){this._stereoCollapsed=t,t&&Oi(),!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 n=i.viewRig||Te(i);i.stereoSaved={ipdFactor:n.ipdFactor,parallaxFactor:n.parallaxFactor}}else i.stereoSaved=null;this._pushViewRig(i)}}}_pushViewRig(e){if(!Me())return Fi(),!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,n=[]){if(!ke())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](...n))}catch(r){return Promise.reject(r)}}_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 n=i.find(r=>r.isActive);return n&&(this._activeModeIndex=n.modeIndex,this._activeViewCount=n.viewCount,(n.viewCount===1||n.viewCount===2)&&this._setStereoCollapsed(n.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||!Me())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 n=(Array.isArray(i)?i:[]).find(a=>a&&a.modeIndex===e),r=n&&Number.isFinite(n.viewCount)?n.viewCount:0,o=this._activeViewCount;return r<1||r>2||o<1?this._requestRenderingMode(e,t):r===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((n,r)=>{i.resolve=n,i.reject=r}),this._msFire=i,this._modeSwitch.request({targetMode:e,targetViewCount:1,currentMode:this._activeModeIndex,currentViewCount:this._activeViewCount,current:this._stereoFactor,steady:1}),this._msLastMs=P(),this._armModeSwitchTick(),i.promise}_requestThenRampUp(e,t){let n=this._msFire!==null&&e===this._activeModeIndex;this._settlePendingDown("superseded",`a request for mode ${e} reversed it`);let r=n?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()),r.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=P(),this._armModeSwitchTick()}_settlePendingDown(e,t){let i=this._msFire;if(!i)return;this._msFire=null;let n=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.`);n.name=e,i.reject(n)}_advanceModeSwitch(){if(!this._modeSwitch.active()){this._msLastMs=null,this._disarmModeSwitchTick();return}let e=P(),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 n of this._windows.values())this._pushViewRig(n)}if(i.fire&&this._msFire){let n=this._msFire;this._msFire=null,this._requestRenderingMode(n.modeIndex,n.win).then(r=>n.resolve(r),r=>{this._startUpRamp(),n.reject(r)})}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())},Di))}_disarmModeSwitchTick(){this._msTick!==null&&(typeof clearTimeout=="function"&&clearTimeout(this._msTick),this._msTick=null)}async _setStereoEnabled(e,t){let i=e?2:1,n=await this._getRenderingModes(t),r=Array.isArray(n)?n:[],o=r.find(a=>a.viewCount===i&&a.isRequestable);if(!o)throw new Error(`[inline3d] setStereoEnabled(${!!e}) found no requestable ${i}-view mode on this display (${r.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"||ke()&&(e.addEventListener("renderingmodechange",t=>{this._onRenderingModeChange(t).catch(()=>{})}),e.addEventListener("hardwaredisplaystatechange",t=>{this._onHardwareDisplayStateChange(t).catch(()=>{})}))}_onHardwareDisplayStateChange(e){let t=Pi(e),i=De(e),n=a=>{a&&(this._hardwareDisplayState=a),this._emitDisplay({type:"hardwaredisplaystatechange",state:a||this._hardwareDisplayState,detail:i})};t&&n(t);let r=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!==r||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;n(c)}}).catch(()=>{t||n(null)})}async _onRenderingModeChange(e){let t=De(e),i=Ai(e),n=null;try{let r=await this._getRenderingModes(null),o=Array.isArray(r)?r:[];n=(i>=0?o.find(a=>a.modeIndex===i):null)||o.find(a=>a.isActive)||null}catch{}n?(this._activeModeIndex=n.modeIndex,this._activeViewCount=n.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:n,detail:t})}_emitDisplay(e,t){let i=this._displayListeners.get(e.type);if(!i)return;let n=t||[e];for(let r of[...i])try{r(...n)}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(!mt.includes(e))throw new TypeError(`[inline3d] on() knows ${mt.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=St.map(i=>this.on(i,e));return()=>{for(let i of t)i()}}async refreshUndock(){if(!Ee())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 n={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(n,null),excluded:new Set,autoExcluded:new Set,overlayObserver:null,sizeObserver:null,resizePending:!1,frames:0,monoFrames:0,fwResult:null,fwResolve:null,fwPromise:null,fwHoldMs:zi(i.firstWovenHoldMs),fwRegAt:P(),fwLayerAt:null,fwStereo:!1,rw:null,rwGone:null};return n.fwPromise=new Promise(r=>{n.fwResolve=r}),this._windows.set(e,n),this._lazy&&this._observer?this._observer.observe(n.observeEl):this._activate(n),n}_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 n of this._windows.values())if(n.observeEl===t.target){i=n;break}i&&(t.isIntersecting?this._activate(i):this._deactivate(i))}}_activate(e){if(!e.layer){this._scanChrome();try{let t=Me()?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=P(),e.fwStereo=!1),this._restartRewoven(e),e.layerLostSent=!1,!this._primedDisplayState&&ke()&&(this._primedDisplayState=!0,this._getRenderingModes(e).catch(()=>{this._primedDisplayState=!1})),Ee()&&this.undock&&!this._undockRead&&(this._undockRead=!0,this.refreshUndock().catch(()=>{})),Ti(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(),n=e.canvas.getBoundingClientRect(),r=i.width*i.height,o=n.width*n.height;if(r<=0||o<=0)return!1;let a=Math.min(i.right,n.right)-Math.max(i.left,n.left),l=Math.min(i.bottom,n.bottom)-Math.max(i.top,n.top);if(a<=0||l<=0)return!1;let c=a*l;return c/r<wt||c/o<wt?!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(G()||!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 n=t.style.willChange&&t.style.willChange!=="auto"?t.style.willChange+", transform":"transform";t.style.willChange=n,t.dataset.inline3dIsolated="1"}try{e.layer.excludeElement(t)}catch{}}_dropExclusion(e,t){if(G())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&&Ce()}_startOverlayScan(e){if(G()||!oe()||typeof MutationObserver!="function")return;let t=e.canvas.parentElement;if(!t)return;let i=()=>{let n=new Set(t.querySelectorAll("[data-inline3d-overlay]"));for(let r of e.autoExcluded)n.has(r)||(e.autoExcluded.delete(r),this._dropExclusion(e,r));for(let r of n)e.autoExcluded.has(r)||(e.autoExcluded.add(r),this._applyExclusion(e,r))};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),n=e.reqW||Math.round((e.canvas.clientWidth||256)*i),r=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/n,a.h/r);c<1&&(o=c,n=Math.max(1,Math.round(n*c)),r=Math.max(1,Math.round(r*c)))}let l=ct(n,r,lt(),{cols:t?2:1});return l.clamped&&(o*=l.scale,n=l.eyeW,r=l.eyeH,e.warnedBufClamp||(e.warnedBufClamp=!0,console.warn(ht("[inline3d]",l)))),e.bufScale=o,{w:n,h:r}}_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,n=t.videoHeight||t.naturalHeight||t.height;return!(i>1)||!(n>0)?null:{w:i/2,h:n}}_checkSceneBuffer(e){let t=e.canvas;if(!t||typeof t.getContext!="function")return;if(e.sceneGl===void 0){let n=null;try{n=t.getContext("webgl2")||t.getContext("webgl")}catch{n=null}e.sceneGl=n&&typeof n.drawingBufferWidth=="number"?n:null}if(!e.sceneGl)return;let i=dt(t,e.sceneGl);i.mismatch&&(e.warnedBufMismatch=!0,console.warn(ft("[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:n}=this._eyeSize(e,t);e.eyeW=i,e.eyeH=n,e.canvas.width=t?i*2:i,e.canvas.height=n,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:n}=this._eyeSize(e);i===e.eyeW&&n===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 n=e.kind==="video"?e.video:e.img;if(!n)return;if(e.kind==="video"&&(n.readyState||0)<2){i&&this._recommitLastFrame(e);return}let r=e.canvas,o=e.ctx,a=n.videoWidth||n.naturalWidth||n.width,l=n.videoHeight||n.naturalHeight||n.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:p,h:_}=this._eyeSize(e,e.sbs);(p!==e.eyeW||_!==e.eyeH)&&this._sizeBuffer(e,e.sbs)}let m=e.bufScale||1,f=e.cornerRadius*m,h=e.feather*m;if(o.clearRect(0,0,r.width,r.height),!e.sbs){le(o,n,0,0,a/2,l,0,0,r.width,r.height,f,h);return}let d=r.width/2,u=Math.min(this._stereoFactor,this._bakedStereo);if(u<1){le(o,n,0,0,a/2,l,0,0,d,r.height,f,h),Bi(o,n,a/2,l,d,r.height,u,f,h);return}f>0||h>0?(le(o,n,0,0,a/2,l,0,0,d,r.height,f,h),le(o,n,a/2,0,a/2,l,d,0,d,r.height,f,h)):o.drawImage(n,0,0,a,l,0,0,r.width,r.height)}_bindTrackingEvents(){let e=this.session;!e||typeof e.addEventListener!="function"||this._trackingSupported&&e.addEventListener(Re,()=>{this._setTrackingState(ae(e)||"unknown")})}_setTrackingState(e){let t=Mt.includes(e)?e:"unknown";if(t===this._trackingState)return;this._trackingState=t,this._applyUntrackedTarget();let i={type:Re,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(ae(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,n=this._bakedTarget;if(i===n)return;let r=this._bakedEaseS>0?t/this._bakedEaseS:1;this._bakedStereo=n>i?Math.min(n,i+r):Math.max(n,i-r)}_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,n)=>{t===this._loopId&&(this._framePending=!1,this._frameCount++,this._frame(i,n))})}catch{this._framePending=!1}}_frame(e,t){if(!this._running)return;this._requestFrame(),this._advanceModeSwitch();let i=this.refSpace?t.getViewerPose(this.refSpace):null,n=i?i.views:null;this._trackBakedStereo(e);for(let r of this._windows.values())if(r.layer){if(r.kind==="scene"){if(n&&r.onFrame){if(r.frames++,n.length<2&&(r.monoFrames++,r.monoFrames%300===1&&typeof console<"u"&&console.debug)){let o=(100*r.monoFrames/Math.max(1,r.frames)).toFixed(1);console.debug(`[inline3d] scene window: ${r.monoFrames} non-stereo view lists in ${r.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{r.onFrame(n,r.layer,t),n.length>=2&&(r.fwStereo=!0,r.warnedBufMismatch||this._checkSceneBuffer(r),r.rw&&(r.rw.stereo=!0))}catch(o){r.frameThrewWarned||(r.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(r,n),r.sbs&&(r.kind==="video"?(r.video&&r.video.readyState||0)>=2:r.img)&&(r.fwStereo=!0,r.rw&&(r.rw.stereo=!0));this._tickFirstWoven(r)}}_tickFirstWoven(e){if(e.rw){this._noteRewovenBox(e);let t=e.rw,i=P();t.stereo&&i-t.at>=e.fwHoldMs?this._settleRewoven(e,!0,"hold-elapsed"):t.at>t.calledAt&&i-t.calledAt>=Vi*e.fwHoldMs&&this._settleRewoven(e,!0,"hold-capped")}e.fwResult||!e.fwStereo||e.fwLayerAt===null||P()-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(P()-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(r=>{t=r}),n=P();return e.rw={promise:i,resolve:t,calledAt:n,at:n,stereo:!1,box:xt(e.canvas)},i}_noteRewovenBox(e){let t=e.rw;if(!t)return;let i=xt(e.canvas);i!==t.box&&(t.box=i,this._restartRewoven(e))}_restartRewoven(e){e.rw&&(e.rw.at=P(),e.rw.stereo=!1)}_settleRewoven(e,t,i){let n=e.rw;n&&(e.rw=null,n.resolve(Object.freeze({woven:t,confirmed:!1,reason:i,ms:Math.round(P()-n.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,N===this&&(N=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 zi(s){return typeof s=="number"&&Number.isFinite(s)&&s>=0?s:Li}function $i(s){return typeof s!="string"?Promise.resolve(s):new Promise((e,t)=>{let i=new Image;i.decoding="async",i.onload=()=>e(i),i.onerror=t,i.src=s})}function le(s,e,t,i,n,r,o,a,l,c,m,f){m>0&&s.roundRect?(s.save(),s.beginPath(),s.roundRect(o,a,l,c,m),s.clip(),s.drawImage(e,t,i,n,r,o,a,l,c),s.restore()):s.drawImage(e,t,i,n,r,o,a,l,c),f>0&&Tt(s,o,a,l,c,f)}function Bi(s,e,t,i,n,r,o,a,l){s.save(),a>0&&s.roundRect&&(s.beginPath(),s.roundRect(n,0,n,r,a),s.clip()),s.drawImage(e,0,0,t,i,n,0,n,r),o>0&&(s.globalAlpha=o,s.drawImage(e,t,0,t,i,n,0,n,r)),s.restore(),l>0&&Tt(s,n,0,n,r,l)}function Tt(s,e,t,i,n,r){let o=Math.min(r,Math.floor(Math.min(i,n)/2));if(o<=0)return;s.save(),s.globalCompositeOperation="destination-out";let a=[[e,t,i,o,[e,t],[e,t+o]],[e,t+n-o,i,o,[e,t+n],[e,t+n-o]],[e,t,o,n,[e,t],[e+o,t]],[e+i-o,t,o,n,[e+i,t],[e+i-o,t]]];for(let[l,c,m,f,h,d]of a){let u=s.createLinearGradient(h[0],h[1],d[0],d[1]);u.addColorStop(0,"rgba(0,0,0,1)"),u.addColorStop(1,"rgba(0,0,0,0)"),s.fillStyle=u,s.fillRect(l,c,m,f)}s.restore()}var Rt="inline3d-call/1",Dt=Object.freeze(["sbs","mono"]),Ui=2.5,J=4,Lt=4,Ie=5,ji=.2,qi=.12,Gi=.05,Xi=150,Ji=5e3,Ki=/^[A-Za-z0-9_-]{16,64}$/,Zi=16;function It(s){let e=new Uint8Array(Zi);return(s||(i=>globalThis.crypto.getRandomValues(i)))(e),At(e)}function Ot(s){let e=new Uint8Array(8);return(s||(i=>globalThis.crypto.getRandomValues(i)))(e),At(e)}function At(s){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",t="",i=0;for(;i+2<s.length;i+=3){let r=s[i]<<16|s[i+1]<<8|s[i+2];t+=e[r>>18&63]+e[r>>12&63]+e[r>>6&63]+e[r&63]}let n=s.length-i;if(n===1){let r=s[i]<<16;t+=e[r>>18&63]+e[r>>12&63]}else if(n===2){let r=s[i]<<16|s[i+1]<<8;t+=e[r>>18&63]+e[r>>12&63]+e[r>>6&63]}return t}function he(s){return typeof s=="string"&&Ki.test(s)}function de(s){if(!s)return null;let e="";if(typeof s=="object")e=s.hash||s.href&&String(s.href).split("#")[1]||"";else{let t=String(s),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 n=decodeURIComponent(t.slice(i+1));return he(n)?n:null}return null}function Oe(s,e){if(!he(e))throw new Error(`@displayxr/inline3d/call: invalid room id "${e}"`);return`${String(s||"").split("#")[0]}#room=${e}`}function Pt(s){if(!s||typeof s!="object"||s.type!=="hello")return null;let e=(t,i,n)=>typeof t=="number"&&Number.isFinite(t)&&t>=i&&t<=n?t:null;return{type:"hello",v:typeof s.v=="number"?s.v:1,format:Dt.includes(s.format)?s.format:"mono",width:e(s.width,1,16384),height:e(s.height,1,16384),baselineMm:e(s.baselineMm,1,1e3),hfovDeg:e(s.hfovDeg,5,170),rectified:s.rectified===!0,sdk:typeof s.sdk=="string"?s.sdk.slice(0,64):null}}function Ft({format:s,width:e,height:t,baselineMm:i,hfovDeg:n,rectified:r}={}){let o={type:"hello",v:1,format:Dt.includes(s)?s:"mono",width:e||0,height:t||0,rectified:!!r,sdk:Rt};return Number.isFinite(i)&&(o.baselineMm=i),Number.isFinite(n)&&(o.hfovDeg=n),o}function Ae(s){if(!s||s.type!=="hint")return null;let e=s.subjectZmm;return typeof e=="number"&&Number.isFinite(e)&&e>=Xi&&e<=Ji?{type:"hint",subjectZmm:e}:null}function Wt(s){return!s||s.type!=="state"?null:{type:"state",muted:s.muted===!0,cameraOff:s.cameraOff===!0,speaking:s.speaking===!0}}function Pe(s){let e=1e3/s,t=-1/0;return i=>i-t<e?!1:(t=i,!0)}function Nt({format:s,woven:e,mono3D:t="auto",lift:i=!1,overBudget:n=!1,failed:r=!1}){return(s==="sbs"?"sbs":"mono")==="sbs"?{route:e?"woven-sbs":"flat-left"}:e?t==="off"||t===!1?{route:"flat",mono3d:"off"}:i?r?{route:"flat",mono3d:"failed"}:n?{route:"flat",mono3d:"budget"}:{route:"lifted",mono3d:"lifted"}:{route:"flat",mono3d:"unavailable"}:{route:"flat"}}function Ht(s){return s==="woven-sbs"?"3D":s==="lifted"?"2D\u21923D":"2D"}function Yi(s,e){return!(s>0)||!(e>0)||e>=180?null:s/2/Math.tan(e/2*Math.PI/180)}function Qi({eyeWidthPx:s,hfovDeg:e,baselineMm:t,subjectZmm:i}){let n=Yi(s,e);return n===null||!(t>0)||!(i>0)?0:n*t/(2*i)}function en(s,e,t=qi){let i=Math.max(0,e*t);return Math.max(-i,Math.min(i,s||0))}function tn(s,e,t=ji){let i=s+t*(e-s);return Math.abs(e-i)<.05?e:i}function Vt(){let s={hello:null,subjectZmm:null,measuredPx:null,depth:0,current:0,target(e){let t=s.measuredPx!==null?s.measuredPx/2:s.hello&&s.subjectZmm?Qi({eyeWidthPx:e,hfovDeg:s.hello.hfovDeg,baselineMm:s.hello.baselineMm,subjectZmm:s.subjectZmm}):0;return en(t+s.depth*Gi*e,e)},step(e){return s.current=tn(s.current,s.target(e)),s.current}};return s}function fe(s,e,t,i,n){let r=Math.abs(i||0),o=Math.min(s-2*r,e*t);o=Math.max(1,o);let a=Math.min(e,o/t);o=a*t;let l=(s-o)/2+(n===0?i:-i);return{sx:Math.max(0,Math.min(s-o,l)),sy:(e-a)/2,sw:o,sh:a}}function Fe(s,e,t){let i=Math.min(s,e*t),n=i/t;return{w:Math.max(2,Math.round(i/2)*2),h:Math.max(2,Math.round(n/2)*2)}}function zt(s,e){let t=s/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 $t({need:s=10,needNoPose:e=30}={}){let t=0,i=0,n=!1;return{feed(r){return n?!0:(i++,r===null?n=i>=e:(t=r>=1?t+1:0,n=t>=s),n)},get live(){return n}}}function Bt(s,e){let t=Math.max(1,e|0),n=s==="sbs"?[6e3,4e3,3e3]:[2500,1800,1400];return n[Math.min(t,n.length)-1]}function H(s,{baseMs:e=1e3,maxMs:t=3e4,rand:i=Math.random}={}){let n=Math.min(t,e*Math.pow(2,Math.max(0,s)));return Math.round(n*(.8+.4*i()))}function ie(s,e){return s>0&&e>0&&s/e>Ui}var We=Object.freeze(["VP9","VP8","AV1"]);function nn(s,e=We){let t=e.indexOf(String(s||"").toUpperCase());return t<0?e.length:t}function Ut(s,e=We){let t=i=>nn(String(i.mimeType||"").split("/")[1],e);return s.map((i,n)=>({c:i,i:n,r:t(i)})).sort((i,n)=>i.r-n.r||i.i-n.i).map(i=>i.c)}function Ne(s,e=We){if(!s)return s;let t=s.includes(`\r
|
|
3
|
+
`)?`\r
|
|
4
|
+
`:`
|
|
5
|
+
`,i=s.split(t),n=i.findIndex(d=>d.startsWith("m=video"));if(n<0)return s;let r=i.findIndex((d,u)=>u>n&&d.startsWith("m="));r<0&&(r=i.length);let o=i.slice(n,r),a=new Map,l=new Map;for(let d of o){let u=d.match(/^a=rtpmap:(\d+) ([\w-]+)\//);u&&a.set(u[1],u[2].toUpperCase());let p=d.match(/^a=fmtp:(\d+) apt=(\d+)/);p&&(l.has(p[2])||l.set(p[2],[]),l.get(p[2]).push(p[1]))}let c=i[n].split(" "),m=c.slice(3),f=[];for(let d of e)for(let u of m)if(a.get(u)===d&&!f.includes(u)){f.push(u);for(let p of l.get(u)||[])m.includes(p)&&!f.includes(p)&&f.push(p)}if(!f.length)return s;let h=m.filter(d=>!f.includes(d));return i[n]=[...c.slice(0,3),...f,...h].join(" "),i.join(t)}var jt=Object.freeze([{urls:"stun:stun.l.google.com:19302"}]),sn=4e3,rn=1e4,on=2e4,an=8e3,ln=1e4;function He(s){let e=Number.isInteger(s)?s:J;return Math.max(2,Math.min(Lt,e))}function qt(s,e){return s<e}var ue=class{constructor({signaling:e,id:t,maxPeers:i,iceServers:n,RTCPeerConnection:r,log:o,unreachableMs:a}={}){this.unreachableMs=a>0?a:ln,this.signaling=e,this.id=t,this.maxPeers=He(i),this.pageIce=n||null,this.iceServers=n||jt,this.PC=r||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:n,onPeerLeft:r,onStream:o,onMessage:a,onPeerState:l,onRefused:c,onSignalingState:m,onGhost:f}){this.localStream=t,this.sendFormat=i||"mono",this.cb={onPeer:n,onPeerLeft:r,onStream:o,onMessage:a,onPeerState:l,onRefused:c,onSignalingState:m,onGhost:f};let h=p=>(..._)=>this.ready?p(..._):this._pending.push(()=>p(..._));this.session=await this.signaling.join(e,{id:this.id,maxPeers:this.maxPeers,onPeerJoined:h(p=>this._onPeerJoined(p)),onPeerLeft:h(p=>this._onPeerLeftSignaling(p)),onSignal:h((p,_)=>this._onSignal(p,_)),onDisconnect:p=>m?.(p?"closed":"reconnecting",p),onPeerUnreachable:h(p=>f?.(p,!0)),onPeerReachable:h(p=>f?.(p,!1)),onReconnect:h(p=>{m?.("connected");for(let _ of p)this._onPeerJoined(_)})}),!this.pageIce&&this.session.iceServers&&this.session.iceServers.length&&(this.iceServers=[...jt,...this.session.iceServers]);let d=this.session.peers||[];if(d.length>=this.maxPeers){this.session.leave();let p=new Error(`@displayxr/inline3d/call: this call is full (${this.maxPeers} participants)`);throw p.code="room-full",p}this.ready=!0;for(let p of d)this._onPeerJoined(p);let u=this._pending;this._pending=[];for(let p of u)p();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"&&qt(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),an)}_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:qt(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 n=i.createDataChannel("dxr-call",{negotiated:!0,id:0,ordered:!0});if(this._wireDc(e,n),e.offerer){let r=this.localStream?this.localStream.getTracks():[],o=r.find(m=>m.kind==="audio"),a=r.find(m=>m.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=r=>{r.candidate&&this._signal(e,{kind:"candidate",candidate:r.candidate.toJSON?r.candidate.toJSON():r.candidate})},i.ontrack=r=>{if(e.stream||(e.stream=new MediaStream),!e.stream.getTracks().includes(r.track)){for(let o of e.stream.getTracks())o.kind===r.track.kind&&e.stream.removeTrack(o);e.stream.addTrack(r.track)}this.cb.onStream?.(e.id,e.stream)},i.onconnectionstatechange=()=>this._onConnState(e,i),this._arm(e,on,()=>{e.pc===i&&i.connectionState!=="connected"&&this._fail(e,"connect-timeout")}),e.offerer&&this._offer(e).catch(r=>this.log("offer-error",{peer:e.id,err:String(r)})),this._setState(e,e.attempts>0?"reconnecting":"connecting"),i}async _offer(e,{iceRestart:t=!1}={}){let i=e.pc,n=await i.createOffer(t?{iceRestart:!0}:void 0);this._canPreferCodecs||(n.sdp=Ne(n.sdp)),await i.setLocalDescription(n),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 n=t.gen|0;try{switch(t.kind){case"offer":{if(i.offerer||(clearTimeout(i.waitTimer),n<i.gen))return;i.offerAt=Date.now(),(n>i.gen||!i.pc)&&this._build(i,n);let r=i.pc;await r.setRemoteDescription({type:"offer",sdp:t.sdp}),this._attachAnswererTracks(i);let o=await r.createAnswer();this._canPreferCodecs||(o.sdp=Ne(o.sdp)),await r.setLocalDescription(o),this._signal(i,{kind:"answer",sdp:r.localDescription.sdp}),this._flushCandidates(i);break}case"answer":if(!i.offerer||n!==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(n!==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(r){this.log("signal-error",{peer:e,kind:t.kind,err:String(r)})}}_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 n of t.getTransceivers()){let r=n.receiver&&n.receiver.track?n.receiver.track.kind:null;if(!r||n.sender.track)continue;let o=i.find(a=>a.kind===r);o&&(n.sender.replaceTrack(o).catch(()=>{}),this.localStream&&n.sender.setStreams&&n.sender.setStreams(this.localStream)),n.direction="sendrecv",r==="video"&&this._preferCodecs(n)}}_preferCodecs(e){let t=globalThis.RTCRtpReceiver&&RTCRtpReceiver.getCapabilities&&RTCRtpReceiver.getCapabilities("video");if(this._canPreferCodecs=!!(e&&e.setCodecPreferences&&t),!!this._canPreferCodecs)try{e.setCodecPreferences(Ut(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,sn,()=>{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,rn,()=>{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=H(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,H(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 n=setTimeout(()=>{e.timers.delete(n),i()},t);e.timers.add(n)}_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 n;try{n=JSON.parse(i.data)}catch{return}if(n&&n.type==="bye")return this._drop(e,"left");this.cb.onMessage?.(e.id,n)}}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 n of this.peers.values())if(n.pc)for(let r of n.pc.getTransceivers())(r.receiver&&r.receiver.track?r.receiver.track.kind:null)===e&&await r.sender.replaceTrack(t).catch(()=>{});await this.tuneSenders()}setSendFormat(e){return this.sendFormat=e,this.tuneSenders()}async tuneSenders(){let e=this.peers.size,t=Bt(this.sendFormat,e);for(let i of this.peers.values())if(i.pc){for(let n of i.pc.getSenders())if(!(!n.track||n.track.kind!=="video"))try{let r=n.getParameters();r.degradationPreference="maintain-resolution",(!r.encodings||!r.encodings.length)&&(r.encodings=[{}]),r.encodings[0].maxBitrate=t*1e3,await n.setParameters(r)}catch(r){this.log("setParameters-error",{peer:i.id,err:String(r)})}}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 Gt={width:{ideal:1280},height:{ideal:720},frameRate:{ideal:30}},Ve={width:{ideal:3840},height:{ideal:1080},frameRate:{ideal:30}},cn=Object.freeze({echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0});function hn(s){return!!s&&(s.name==="NotReadableError"||s.name==="TrackStartError"||/in use|busy/i.test(s.message||""))}function Xt(s){return s.length&&s.every(e=>e.busy)?"camera-busy":"no-camera"}function ze(s){return/stereo|\b3d\b|\bsbs\b|dual/i.test(s||"")}async function Jt(s="auto",e={}){let t=e.mediaDevices||globalThis.navigator&&navigator.mediaDevices,i=e.log||(()=>{}),n=[],r=e.calibration||{};if(s&&typeof s=="object"&&typeof s.getVideoTracks=="function"){let u=s.getVideoTracks()[0],p=u?u.getSettings():{},_=e.format==="sbs"?"sbs":"mono";return{stream:s,format:_,width:p.width||0,height:p.height||0,deviceId:p.deviceId||null,label:u?u.label:"",owned:!1,skipped:n,calibration:r}}if(!t||!t.getUserMedia)throw Object.assign(new Error("getUserMedia is not available (insecure context?)"),{code:"no-camera"});let o=async u=>{let p=await t.getUserMedia({video:u,audio:!1}),_=p.getVideoTracks()[0],b=_?_.getSettings():{};if(!_||_.readyState==="ended"||!(b.width>0)||!(b.height>0))throw p.getTracks().forEach(k=>k.stop()),Object.assign(new Error("the camera opened but delivers no picture (0x0)"),{name:"NotReadableError"});let x=b.displayxrStereo&&b.displayxrStereo.layout==="side-by-side"?b.displayxrStereo:null;return{stream:p,track:_,width:b.width,height:b.height,deviceId:b.deviceId||null,label:_.label||"",stereo:x}},a=(u,p)=>{n.push({label:u,error:`${p.name}: ${p.message}`,busy:hn(p)}),i("camera-skip",{label:u,error:p.name})},l=u=>u&&u.stream.getTracks().forEach(p=>p.stop()),c=(u,p)=>({stream:u.stream,format:p,width:u.width,height:u.height,deviceId:u.deviceId,label:u.label,owned:!0,skipped:n,calibration:{rectified:!1,...p==="sbs"&&u.stereo?{rectified:!!u.stereo.rectified,...u.stereo.baselineMm>0?{baselineMm:u.stereo.baselineMm}:{},...u.stereo.horizontalFovDeg>0?{hfovDeg:u.stereo.horizontalFovDeg}:{}}:{},...r}});if(typeof s=="string"&&!["auto","stereo","mono"].includes(s)){let u;try{u=await o({deviceId:{exact:s},...Ve})}catch(p){throw a(s,p),Object.assign(new Error(`camera unavailable: ${p.message}`),{code:Xt(n),skipped:n})}return ie(u.width,u.height)?c(u,"sbs"):(l(u),c(await o({deviceId:{exact:s},...Gt}),"mono"))}let m=new Set;if(s!=="mono"){let u=[];try{u=(await t.enumerateDevices()).filter(p=>p.kind==="videoinput"&&p.deviceId&&ze(p.label))}catch{}for(let p of u){m.add(p.deviceId);let _=null;try{_=await o({deviceId:{exact:p.deviceId},...Ve})}catch(b){a(p.label,b);continue}if(ie(_.width,_.height))return i("camera-sbs",{label:_.label,width:_.width,height:_.height,direct:!0}),c(_,"sbs");l(_)}}let f=null;try{f=await o(Gt)}catch(u){a("default",u)}if(s==="mono"&&f)return c(f,"mono");if(f&&ie(f.width,f.height))return c(f,"sbs");let h=[];try{h=(await t.enumerateDevices()).filter(u=>u.kind==="videoinput")}catch{}h.sort((u,p)=>Number(ze(p.label))-Number(ze(u.label)));for(let u of h){if(!u.deviceId||f&&u.deviceId===f.deviceId||m.has(u.deviceId))continue;let p=null;try{p=await o({deviceId:{exact:u.deviceId},...Ve})}catch(_){a(u.label,_);continue}if(ie(p.width,p.height))return l(f),i("camera-sbs",{label:p.label,width:p.width,height:p.height}),c(p,"sbs");l(p)}if(f)return s==="stereo"&&i("camera-no-stereo",{fallback:f.label}),c(f,"mono");let d=Xt(n);throw Object.assign(new Error(d==="camera-busy"?"every camera is in use by another app (e.g. eye tracking)":"no camera could be opened"),{code:d,skipped:n})}async function Kt(s={}){let e=s.mediaDevices||globalThis.navigator&&navigator.mediaDevices;try{return(await e.getUserMedia({audio:{...cn},video:!1})).getAudioTracks()[0]||null}catch(t){return(s.log||(()=>{}))("mic-skip",{error:t&&t.name}),null}}var Yt=[[-1,7,10,15,20,26,18,20,24,30,18],[-1,10,16,26,18,24,16,18,22,22,26]],Qt=[[-1,1,1,1,1,1,2,2,2,2,4],[-1,1,1,1,2,2,4,4,4,5,5]],dn=[1,0],$e=10;function ei(s){let e=(16*s+128)*s+64;if(s>=2){let t=Math.floor(s/7)+2;e-=(25*t-10)*t-55,s>=7&&(e-=36)}return e}var Zt=(s,e)=>Math.floor(ei(s)/8)-Yt[e][s]*Qt[e][s];function Be(s,e){let t=0;for(let i=7;i>=0;i--)t=t<<1^(t>>>7)*285,t^=(e>>>i&1)*s;return t}function fn(s){let e=new Array(s-1).fill(0);e.push(1);let t=1;for(let i=0;i<s;i++){for(let n=0;n<e.length;n++)e[n]=Be(e[n],t),n+1<e.length&&(e[n]^=e[n+1]);t=Be(t,2)}return e}function un(s,e){let t=e.map(()=>0);for(let i of s){let n=i^t.shift();t.push(0),e.forEach((r,o)=>t[o]^=Be(r,n))}return t}function pn(s,e={}){let t=e.ecl==="L"?0:1,i=[...new TextEncoder().encode(String(s))],n=1;for(;n<=$e&&!(4+(n<=9?8:16)+i.length*8<=Zt(n,t)*8);n++);if(n>$e)throw new Error(`qrEncode: ${i.length} bytes is too long for a version-${$e} code`);let r=[],o=(g,y)=>{for(let v=y-1;v>=0;v--)r.push(g>>>v&1)};o(4,4),o(i.length,n<=9?8:16);for(let g of i)o(g,8);let a=Zt(n,t)*8;o(0,Math.min(4,a-r.length)),o(0,(8-r.length%8)%8);for(let g=236;r.length<a;g^=253)o(g,8);let l=[];for(let g=0;g<r.length;g+=8)l.push(r.slice(g,g+8).reduce((y,v)=>y<<1|v,0));let c=Qt[t][n],m=Yt[t][n],f=Math.floor(ei(n)/8),h=c-f%c,d=Math.floor(f/c),u=fn(m),p=[];for(let g=0,y=0;g<c;g++){let v=l.slice(y,y+d-m+(g<h?0:1));y+=v.length;let M=un(v,u);g<h&&v.push(0),p.push(v.concat(M))}let _=[];for(let g=0;g<p[0].length;g++)for(let y=0;y<p.length;y++)(g!==d-m||y>=h)&&_.push(p[y][g]);let b=n*4+17,x=Array.from({length:b},()=>new Array(b).fill(!1)),k=Array.from({length:b},()=>new Array(b).fill(!1)),w=(g,y,v)=>{x[y][g]=v,k[y][g]=!0};for(let g=0;g<b;g++)w(6,g,g%2===0),w(g,6,g%2===0);let I=(g,y)=>{for(let v=-4;v<=4;v++)for(let M=-4;M<=4;M++){let L=Math.max(Math.abs(M),Math.abs(v)),C=g+M,W=y+v;C>=0&&C<b&&W>=0&&W<b&&w(C,W,L!==2&&L!==4)}};I(3,3),I(b-4,3),I(3,b-4);let E=[];if(n>1){let g=Math.floor(n/7)+2,y=Math.ceil((n*4+4)/(g*2-2))*2;E.push(6);for(let v=b-7;E.length<g;v-=y)E.splice(1,0,v)}for(let g=0;g<E.length;g++)for(let y=0;y<E.length;y++)if(!(g===0&&y===0||g===0&&y===E.length-1||g===E.length-1&&y===0))for(let v=-2;v<=2;v++)for(let M=-2;M<=2;M++)w(E[g]+M,E[y]+v,Math.max(Math.abs(M),Math.abs(v))!==1);let D=g=>{let y=dn[t]<<3|g,v=y;for(let C=0;C<10;C++)v=v<<1^(v>>>9)*1335;let M=(y<<10|v)^21522,L=C=>(M>>>C&1)!==0;for(let C=0;C<=5;C++)w(8,C,L(C));w(8,7,L(6)),w(8,8,L(7)),w(7,8,L(8));for(let C=9;C<15;C++)w(14-C,8,L(C));for(let C=0;C<8;C++)w(b-1-C,8,L(C));for(let C=8;C<15;C++)w(8,b-15+C,L(C));w(8,b-8,!0)};if(D(0),n>=7){let g=n;for(let v=0;v<12;v++)g=g<<1^(g>>>11)*7973;let y=n<<12|g;for(let v=0;v<18;v++){let M=(y>>>v&1)!==0,L=b-11+v%3,C=Math.floor(v/3);w(L,C,M),w(C,L,M)}}let T=0;for(let g=b-1;g>=1;g-=2){g===6&&(g=5);for(let y=0;y<b;y++)for(let v=0;v<2;v++){let M=g-v,C=(g+1&2)===0?b-1-y:y;!k[C][M]&&T<_.length*8&&(x[C][M]=(_[T>>>3]>>>7-(T&7)&1)!==0,T++)}}let A=g=>{for(let y=0;y<b;y++)for(let v=0;v<b;v++){if(k[y][v])continue;let M;switch(g){case 0:M=(v+y)%2===0;break;case 1:M=y%2===0;break;case 2:M=v%3===0;break;case 3:M=(v+y)%3===0;break;case 4:M=(Math.floor(v/3)+Math.floor(y/2))%2===0;break;case 5:M=v*y%2+v*y%3===0;break;case 6:M=(v*y%2+v*y%3)%2===0;break;default:M=((v+y)%2+v*y%3)%2===0}M&&(x[y][v]=!x[y][v])}},R=Number.isInteger(e.mask)?e.mask:-1;if(R<0){let g=1/0;for(let y=0;y<8;y++){A(y),D(y);let v=mn(x,b);v<g&&(g=v,R=y),A(y)}}return A(R),D(R),{version:n,size:b,mask:R,modules:x}}function mn(s,e){let t=0,i=[];for(let o=0;o<e;o++)i.push(s[o]);for(let o=0;o<e;o++)i.push(s.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 m=l.indexOf(c);m>=0;m=l.indexOf(c,m+1))t+=40}let n=0;for(let o=0;o<e;o++)for(let a=0;a<e;a++)if(s[o][a]&&n++,a<e-1&&o<e-1){let l=s[o][a];l===s[o][a+1]&&l===s[o+1][a]&&l===s[o+1][a+1]&&(t+=3)}let r=e*e;return t+=Math.floor(Math.abs(n*20-r*10)/r)*10,t}function ti(s,e,{px:t=4,dark:i="#000",light:n="#fff",ecl:r="M"}={}){let o=pn(e,{ecl:r}),a=o.size+8;s.width=s.height=a*t;let l=s.getContext("2d");l.fillStyle=n,l.fillRect(0,0,a*t,a*t),l.fillStyle=i;for(let c=0;c<o.size;c++)for(let m=0;m<o.size;m++)o.modules[c][m]&&l.fillRect((m+4)*t,(c+4)*t,t,t);return o}var ni=Object.freeze({azure:"#4da3ff",violet:"#9b7bff",magenta:"#ff4fa3",sunset:"#ff7a45",amber:"#ffc23d",lime:"#9be15d",mint:"#35e0b0",ice:"#8fe3ff"}),si=s=>typeof s=="string"&&ni[s.toLowerCase()]||s,ii="dxr-call-style",gn=`
|
|
6
|
+
.dxr-call-host{--dxr-accent:#4da3ff;--dxr-ink:#fff;--dxr-shell:rgba(16,17,22,.92);--dxr-danger:#ff5a5f;
|
|
7
|
+
display:flex;flex-direction:column;gap:12px;color:var(--dxr-ink);
|
|
8
|
+
font:14px/1.4 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;}
|
|
9
|
+
.dxr-call-host *{box-sizing:border-box;}
|
|
10
|
+
.dxr-call-hidden{display:none !important;}
|
|
11
|
+
.dxr-call-banner{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:9px 14px;border-radius:10px;
|
|
12
|
+
background:var(--dxr-shell);border:1px solid rgba(255,255,255,.12);font-size:13px;}
|
|
13
|
+
.dxr-call-banner a{color:var(--dxr-accent);font-weight:600;}
|
|
14
|
+
/* \u2500\u2500 grid: bare boxes, nothing that makes a render surface \u2500\u2500 */
|
|
15
|
+
.dxr-call-grid{display:grid;gap:10px;grid-template-columns:1fr;margin-inline:auto;width:100%;
|
|
16
|
+
/* Fit the tiles AND the footer (self view + bar) in one viewport: tiles are 16:9 per eye, so
|
|
17
|
+
the grid's width is capped by the height left after --dxr-call-reserve (the footer). */
|
|
18
|
+
--dxr-call-h:var(--dxr-call-fit,calc(100vh - var(--dxr-call-reserve,150px)));max-width:calc(var(--dxr-call-h)*16/9);}
|
|
19
|
+
.dxr-call-grid[data-n="2"]{max-width:calc(var(--dxr-call-h)*32/9);}
|
|
20
|
+
.dxr-call-grid[data-layout="speaker"]:not([data-n="1"]){max-width:calc(var(--dxr-call-h)*4/3);}
|
|
21
|
+
.dxr-call-grid[data-n="2"],.dxr-call-grid[data-n="3"]{grid-template-columns:1fr 1fr;}
|
|
22
|
+
.dxr-call-grid[data-layout="speaker"]{grid-template-columns:repeat(3,1fr);}
|
|
23
|
+
.dxr-call-grid[data-layout="speaker"] .dxr-call-tile--main{grid-column:1/-1;}
|
|
24
|
+
.dxr-call-grid[data-layout="speaker"][data-n="1"]{grid-template-columns:1fr;}
|
|
25
|
+
.dxr-call-tile{position:relative;min-width:0;}
|
|
26
|
+
.dxr-call-stage{position:relative;background:#000;}
|
|
27
|
+
.dxr-call-stage>canvas{display:block;width:100%;height:100%;}
|
|
28
|
+
/* a LIFTED tile: its <video> is mounted in the stage for lift() (which floats its canvas over the
|
|
29
|
+
element's rect, z-index 1); the flat canvas sits above it until lift is live, then hides. */
|
|
30
|
+
.dxr-call-stage>video.dxr-call-liftsrc{position:absolute;left:0;top:0;width:100%;height:100%;object-fit:cover;}
|
|
31
|
+
.dxr-call-stage>canvas.dxr-call-liftflat{position:relative;z-index:1;}
|
|
32
|
+
.dxr-call-talk{height:3px;margin-top:4px;background:transparent;}
|
|
33
|
+
.dxr-call-tile--speaking .dxr-call-talk{background:var(--dxr-accent);}
|
|
34
|
+
/* \u2500\u2500 partial overlays on a tile \u2500\u2500 */
|
|
35
|
+
.dxr-call-badge{position:absolute;left:8px;top:8px;z-index:2;display:flex;align-items:center;gap:6px;
|
|
36
|
+
padding:3px 8px;border-radius:99px;background:var(--dxr-shell);font-size:11px;font-weight:600;
|
|
37
|
+
letter-spacing:.4px;will-change:transform;pointer-events:none;}
|
|
38
|
+
.dxr-call-badge b{font-weight:800;color:var(--dxr-accent);}
|
|
39
|
+
.dxr-call-badge svg{width:13px;height:13px;fill:var(--dxr-danger);}
|
|
40
|
+
.dxr-call-state{position:absolute;left:50%;top:50%;z-index:2;transform:translate(-50%,-50%);max-width:70%;
|
|
41
|
+
padding:8px 14px;border-radius:99px;background:var(--dxr-shell);font-size:13px;text-align:center;
|
|
42
|
+
will-change:transform;pointer-events:none;}
|
|
43
|
+
.dxr-call-cover{position:absolute;inset:0;z-index:1;background:#000;}
|
|
44
|
+
/* \u2500\u2500 empty room / lobby \u2500\u2500 */
|
|
45
|
+
.dxr-call-panel{padding:18px;border-radius:12px;background:var(--dxr-shell);border:1px solid rgba(255,255,255,.1);}
|
|
46
|
+
.dxr-call-panel h3{margin:0 0 6px;font-size:17px;}
|
|
47
|
+
.dxr-call-panel p{margin:0 0 12px;opacity:.75;}
|
|
48
|
+
.dxr-call-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;}
|
|
49
|
+
.dxr-call-btn{appearance:none;border:1px solid rgba(255,255,255,.18);background:rgba(255,255,255,.08);color:inherit;
|
|
50
|
+
font:600 13px/1 system-ui,-apple-system,"Segoe UI",sans-serif;padding:9px 14px;border-radius:9px;cursor:pointer;}
|
|
51
|
+
.dxr-call-btn:hover{background:rgba(255,255,255,.16);}
|
|
52
|
+
.dxr-call-btn:focus-visible{outline:2px solid var(--dxr-accent);outline-offset:2px;}
|
|
53
|
+
.dxr-call-btn--primary{background:var(--dxr-accent);border-color:var(--dxr-accent);color:#07111d;}
|
|
54
|
+
.dxr-call-btn--primary:hover{background:var(--dxr-accent);}
|
|
55
|
+
.dxr-call-btn--danger{background:var(--dxr-danger);border-color:var(--dxr-danger);color:#fff;}
|
|
56
|
+
.dxr-call-select{font:inherit;color:inherit;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);
|
|
57
|
+
border-radius:8px;padding:7px 9px;max-width:260px;}
|
|
58
|
+
.dxr-call-invite{display:flex;gap:14px;align-items:flex-start;flex-wrap:wrap;}
|
|
59
|
+
.dxr-call-invite input{flex:1 1 240px;min-width:0;font:12px ui-monospace,Menlo,monospace;color:inherit;
|
|
60
|
+
background:rgba(0,0,0,.35);border:1px solid rgba(255,255,255,.14);border-radius:8px;padding:8px;}
|
|
61
|
+
.dxr-call-invite canvas{width:132px;height:132px;image-rendering:pixelated;background:#fff;}
|
|
62
|
+
/* \u2500\u2500 footer: self view + bar, BELOW the grid (over no tile) \u2500\u2500 */
|
|
63
|
+
.dxr-call-foot{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;}
|
|
64
|
+
.dxr-call-self{width:200px;flex:none;}
|
|
65
|
+
.dxr-call-host--lobby .dxr-call-self{width:min(560px,100%);}
|
|
66
|
+
.dxr-call-self .dxr-call-badge b{color:var(--dxr-ink);}
|
|
67
|
+
.dxr-call-bar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:8px 10px;border-radius:14px;
|
|
68
|
+
background:var(--dxr-shell);border:1px solid rgba(255,255,255,.1);will-change:transform;}
|
|
69
|
+
.dxr-call-host--lobby .dxr-call-bar{display:none;}
|
|
70
|
+
.dxr-call-ib{appearance:none;border:0;width:40px;height:40px;border-radius:50%;padding:9px;cursor:pointer;
|
|
71
|
+
background:rgba(255,255,255,.1);color:var(--dxr-ink);}
|
|
72
|
+
.dxr-call-ib:hover{background:rgba(255,255,255,.2);}
|
|
73
|
+
.dxr-call-ib:focus-visible{outline:2px solid var(--dxr-accent);outline-offset:2px;}
|
|
74
|
+
.dxr-call-ib svg{width:100%;height:100%;fill:currentColor;display:block;}
|
|
75
|
+
.dxr-call-ib[aria-pressed="true"]{background:var(--dxr-ink);color:#111;}
|
|
76
|
+
.dxr-call-ib--leave{background:var(--dxr-danger);width:52px;border-radius:20px;}
|
|
77
|
+
.dxr-call-ib--leave:hover{background:var(--dxr-danger);}
|
|
78
|
+
.dxr-call-depth{display:flex;align-items:center;gap:6px;padding:0 8px;font-size:12px;opacity:.9;}
|
|
79
|
+
.dxr-call-depth input{width:110px;accent-color:var(--dxr-accent);}
|
|
80
|
+
.dxr-call-note{font-size:12px;opacity:.65;}
|
|
81
|
+
`;function ri(s=document){if(s.getElementById(ii))return;let e=s.createElement("style");e.id=ii,e.textContent=gn,(s.head||s.documentElement).appendChild(e)}var B=s=>`<svg viewBox="0 0 24 24" aria-hidden="true"><path d="${s}"/></svg>`,V={mic:B("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:B("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:B("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:B("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:B("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:B("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:B("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 S(s,e={},t=[]){let i=document.createElement(s);for(let[n,r]of Object.entries(e))r!=null&&(n==="class"?i.className=r:n==="html"?i.innerHTML=r:n==="text"?i.textContent=r:n.startsWith("on")&&typeof r=="function"?i.addEventListener(n.slice(2),r):n in i&&typeof r!="string"?i[n]=r:i.setAttribute(n,r));for(let n of[].concat(t))n&&i.appendChild(typeof n=="string"?document.createTextNode(n):n);return i}var O=(s,e)=>s&&s.classList.toggle("dxr-call-hidden",!e);var je="dxr-call:",_n=["joined","left","peer","peerleft","state","format","speaker","quality","error","warning","session"],Ue="[inline3d/call] <dxr-call>",K=s=>s!=null&&!/^(false|0|off|no)$/i.test(String(s).trim()),oi=s=>{if(s==null||String(s).trim()==="")return;let e=/^\s*([0-9.]+)\s*\/\s*([0-9.]+)\s*$/.exec(String(s)),t=e?+e[1]/+e[2]:+s;return Number.isFinite(t)?t:void 0},F=s=>s==null||String(s).trim()===""?void 0:String(s).trim();function qe(s){let e=typeof s=="function"?s:o=>s&&typeof s.getAttribute=="function"?s.getAttribute(o):null,t={},i=(o,a)=>{a!==void 0&&(t[o]=a)};i("room",F(e("room")));let n=F(e("signaling"));n&&(t.signaling=Y(n,F(e("key"))?{key:F(e("key"))}:{})),i("key",F(e("key"))),i("camera",F(e("camera"))),i("layout",F(e("layout"))),i("accent",F(e("accent"))),i("maxPeers",oi(e("max-peers"))),K(e("no-ui"))&&(t.ui=!1),K(e("auto-join"))&&(t.autoJoin=!0);let r=F(e("mono3d"));return r&&/^(off|false|0|no)$/i.test(r)&&(t.mono3D="off"),K(e("no-audio"))&&(t.audio=!1),K(e("no-self-view"))&&(t.selfView=!1),K(e("no-auto-converge"))&&(t.autoConverge=!1),i("tileAspect",oi(e("tile-aspect"))),i("inviteBase",F(e("invite-base"))),i("browserUrl",F(e("browser-url"))),K(e("debug"))&&(t.debug=!0),t}var vn=typeof HTMLElement=="function"?HTMLElement:class{},Z=class s extends vn{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={...qe(this),...this.options&&typeof this.options=="object"?this.options:{}},i=this.constructor.mount||s.mount||Ge;this._pending=new Promise(n=>n(i(this,t))).then(n=>{if(this._pending=null,e!==this._gen)return n.leave(),null;if(this.call=n,this._off=_n.map(r=>n.on(r,o=>this._dispatch(r,o))),this._off.push(n.on("error",r=>console.warn(`${Ue} ${r.code}: ${r.message}`))),this._dispatch("ready",{call:n}),n.state==="in-call"){this._dispatch("joined",{room:n.room,id:n.id});for(let r of n.peers)this._dispatch("peer",{id:r.id})}return n},n=>{throw this._pending=null,this._dispatch("error",{code:"mount-failed",message:String(n&&n.message||n),error:n||null}),console.warn(`${Ue} mount failed: ${String(n&&n.message||n)}`),n}),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(je+e,{detail:t,bubbles:!0,composed:!0}))}};function pe(s="dxr-call",e=globalThis.customElements){if(!e||typeof e.define!="function")return!1;let t=e.get(s);return t?(t!==Z&&console.warn(`${Ue} <${s}> is already defined by another class; leaving it`),!1):(e.define(s,Z),!0)}function Q(s,e){let t=new Error(`@displayxr/inline3d/call: ${e}`);return t.code=s,t}async function ai(s){let e=await globalThis.crypto.subtle.digest("SHA-256",new TextEncoder().encode(String(s)));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}var Xe="wss://dxr-signal.displayxr.workers.dev";function Y(s=Xe,e={}){if(!s||typeof s!="string")throw Q("no-signaling-url","dxrSignaling(url): url must be a ws:// or wss:// string (omit it for the hosted DisplayXR server)");let t=s.replace(/\/+$/,""),i=e.WebSocket||globalThis.WebSocket,n=e.pingMs||2e4;return{name:"dxr",url:t,async join(r,o){let a=await ai(r),l=`${t}/v1/connect?k=${a}${typeof e.key=="string"&&e.key?`&key=${encodeURIComponent(e.key)}`:""}`,c=null,m=!1,f=0,h=null,d=new Set,u=[],p=k=>new Promise((w,I)=>{let E=!1,D=!1,T=new i(l);c=T;let A=R=>{if(!E){E=!0;try{T.close()}catch{}I(R)}};T.onopen=()=>{T.send(JSON.stringify({t:"join",v:1,room:r,id:o.id,max:o.maxPeers}))},T.onmessage=R=>{let g;try{g=JSON.parse(typeof R.data=="string"?R.data:String(R.data))}catch{return}switch(g.t){case"welcome":{f=0;let y=Array.isArray(g.peers)?g.peers.filter(M=>typeof M=="string"):[];clearInterval(h),h=setInterval(()=>_({t:"ping"}),n);let v=u;u=[];for(let M of v)_(M);if(k){let M=new Set(y);for(let L of d)M.has(L)||o.onPeerLeft?.(L);d=M,o.onReconnect?.(y)}else d=new Set(y);E=!0,D=!0,w({id:g.id,peers:y,iceServers:Array.isArray(g.iceServers)?g.iceServers:void 0,max:g.max});break}case"full":m=!0,A(Q("room-full",`this call is full (${g.max} participants)`));break;case"error":!E&&["bad-room","bad-id","bad-version"].includes(g.code)?(m=!0,A(Q(g.code,g.message||g.code))):!E&&g.code==="id-taken"&&A(Q("id-taken","peer id still held; retrying"));break;case"peer-joined":typeof g.id=="string"&&!d.has(g.id)&&(d.add(g.id),o.onPeerJoined?.(g.id));break;case"peer-left":typeof g.id=="string"&&(d.delete(g.id),o.onPeerLeft?.(g.id));break;case"signal":typeof g.from=="string"&&o.onSignal?.(g.from,g.data);break}},T.onerror=()=>A(Q("signaling-unreachable",`cannot reach ${t}`)),T.onclose=()=>{clearInterval(h),A(Q("signaling-closed","signalling closed before joining")),D&&!m&&c===T&&b()}}),_=k=>{c&&c.readyState===1?c.send(JSON.stringify(k)):m||u.push(k)},b=()=>{o.onDisconnect?.();let k=()=>{m||p(!0).catch(w=>{if(m||w&&w.code==="room-full"){o.onDisconnect?.(w);return}setTimeout(k,H(f++,{baseMs:500,maxMs:15e3}))})};setTimeout(k,H(f++,{baseMs:300,maxMs:15e3}))};return{...await p(!1),send:(k,w)=>_({t:"signal",to:k,data:w}),leave:()=>{if(!m){m=!0,clearInterval(h);try{c&&c.readyState===1&&c.send(JSON.stringify({t:"leave"})),c&&c.close(1e3,"leave")}catch{}}}}}}}function me(s,e,t,i,n,r,o,a,l,c,m){if(r<0||r+a>t||o<0)return-1;let f=0,h=0,d=0,u=a*l;for(let b=0;b<l;b++){let x=(n+b)*e+i,k=(o+b)*e+t+r;for(let w=0;w<a;w++){let I=s[k+w];f+=I,h+=I*I,d+=s[x+w]*I}}let p=f/u,_=h/u-p*p;return _<1?-1:(d/u-c*p)/(m*Math.sqrt(_))}function yn(s,e,t,i,n,r){let o=0,a=0;for(let m=0;m<r;m++){let f=(i+m)*e+t;for(let h=0;h<n;h++){let d=s[f+h];o+=d,a+=d*d}}let l=n*r,c=o/l;return{mean:c,std:Math.sqrt(Math.max(0,a/l-c*c))}}function Je(s,e,t,i,n,r,o,{dMin:a,dMax:l,dyMax:c=2,uniq:m}={}){let f=e/2,{mean:h,std:d}=yn(s,e,i,n,r,o);if(d<6)return null;let u=-2,p=0,_=0,b=new Map,x=(R,g,y,v,M)=>{for(let L=v;L<=M;L++){let C=n+L;if(!(C<0||C+o>t))for(let W=R;W<=g;W+=y){let se=me(s,e,f,i,n,i-W,C,r,o,h,d);se>(b.get(W)??-2)&&b.set(W,se),se>u&&(u=se,p=W,_=L)}}},k=l-a>8;if(x(a,l,k?2:1,-c,c),k&&u>-1){let R=p,g=_;x(Math.max(a,R-2),Math.min(l,R+2),1,Math.max(-c,g-1),Math.min(c,g+1))}if(u<-1)return null;let w=-2,I=R=>{let g=-2;for(let y=-c;y<=c;y++){let v=n+y;if(!(v<0||v+o>t))for(let M=R-1;M<=R+1;M++)g=Math.max(g,me(s,e,f,i,n,i-M,v,r,o,h,d))}return g};for(let[R,g]of b){if(Math.abs(R-p)<3||g<=w)continue;let v=g>=(b.get(R-2)??-2)&&g>=(b.get(R+2)??-2)&&g>0?I(R):g;v>w&&(w=v)}if(l-a>12&&w>-2&&u-w<(m??.08))return null;let E=me(s,e,f,i,n,i-(p-1),n+_,r,o,h,d),D=me(s,e,f,i,n,i-(p+1),n+_,r,o,h,d),T=0,A=E-2*u+D;return E>-1&&D>-1&&A<0&&(T=Math.max(-.5,Math.min(.5,.5*(E-D)/A))),{d:p+T,dy:_,c:u}}function bn(s,e,t,i={}){let n=e/2,r=i.block||Math.max(8,Math.round(n/20)),o=i.step||Math.round(r*1.5),a=i.dMax??Math.round(n*.3),l=i.dMin??-Math.round(n*.05),c=Math.round(n*(i.roiX0??.15)),m=Math.round(n*(i.roiX1??.85))-r,f=Math.round(t*(i.roiY0??.05)),h=Math.round(t*(i.roiY1??.85))-r,d=[];for(let u=f;u<=h;u+=o)for(let p=c;p<=m;p+=o){let _=Je(s,e,t,p,u,r,r,{dMin:l,dMax:a,dyMax:i.dyMax??2,uniq:i.uniq});_&&_.c>=(i.minNcc??.8)&&d.push({x:p,y:u,..._})}return d}function wn(s,{tol:e=2,minFrac:t=.12,minBlocks:i=3}={}){if(!s.length)return null;let n=Math.max(i,Math.ceil(s.length*t)),r=s.map(o=>o.d).sort((o,a)=>a-o);for(let o of r){let a=s.filter(l=>Math.abs(l.d-o)<=e);if(a.length>=n){let l=a.map(c=>c.d).sort((c,m)=>c-m);return{d:l[l.length>>1],members:a}}}return null}function xn(s,e){let t=Math.min(...s.map(l=>l.y)),n=s.filter(l=>l.y<=t+2*e).map(l=>l.x),r=Math.min(...n),o=Math.max(...n)+e,a=o-r;return{x:(r+o)/2,y:t+.4*1.3*a}}function Sn(s,e,t,i={}){let n=e/2,r=i.block||Math.max(8,Math.round(n/20)),o=i.dMax??Math.round(n*.3),a=i.dMin??-Math.round(n*.05),l=i.focus||null,c="focus",m=0,f=null;if(!l){let k=bn(s,e,t,{...i,block:r,dMax:o,dMin:a});m=k.length;let w=wn(k,i);if(!w)return null;l=xn(w.members,r),f=w.d,c="mode"}let h=Math.round(r*(i.refineW??3)),d=Math.round(r*(i.refineH??1.5)),u=Math.round(Math.max(0,Math.min(n-h,l.x-h/2))),p=Math.round(Math.max(0,Math.min(t-d,l.y-d/2))),_=f===null?a:Math.max(a,Math.floor(f)-4),b=f===null?o:Math.min(o,Math.ceil(f)+4),x=Je(s,e,t,u,p,h,d,{dMin:_,dMax:b,dyMax:i.dyMax??2});return x&&x.c>=(i.minNcc??.8)?{d:x.d,x:l.x,y:l.y,c:x.c,method:c,blocks:m}:f!==null?{d:f,x:l.x,y:l.y,c:0,method:c,blocks:m}:null}function ci(s,e){let t=new Uint8Array(e);for(let i=0,n=0;i<e;i++,n+=4)t[i]=s[n]*77+s[n+1]*150+s[n+2]*29>>8;return t}function hi({n:s=3}={}){let e=[],t={value:null,push(i){if(i===null||!Number.isFinite(i))return t.value;e.push(i),e.length>s&&e.shift();let n=[...e].sort((r,o)=>r-o);return t.value=n[n.length>>1],t.value},reset(){e.length=0,t.value=null}};return t}function li(s,e,t,i,n,r){let o=new Float32Array(n*r);for(let a=0;a<r;a++)for(let l=0;l<n;l++)o[a*n+l]=s[(i+a)*e+t+l];return o}function Mn(s,e,t,i,n,r,o,a,l,c){let m=e/2,f=n*r,h=0,d=0;for(let x=0;x<f;x++)h+=i[x],d+=i[x]*i[x];h/=f;let u=Math.sqrt(Math.max(1e-6,d/f-h*h)),p=-2,_=o,b=a;for(let x=Math.max(0,a-c);x<=Math.min(t-r,a+c);x++)for(let k=Math.max(0,o-l);k<=Math.min(m-n,o+l);k++){let w=0,I=0,E=0;for(let R=0;R<r;R++){let g=(x+R)*e+k;for(let y=0;y<n;y++){let v=s[g+y];w+=v,I+=v*v,E+=v*i[R*n+y]}}let D=w/f,T=I/f-D*D;if(T<1)continue;let A=(E/f-D*h)/(Math.sqrt(T)*u);A>p&&(p=A,_=k,b=x)}return{x:_,y:b,c:p}}function di({fullEveryMs:s=2e3,dWin:e=4,rx:t=12,ry:i=8,minTrackNcc:n=.75,jump:r=8}={}){let o=null,a=null;return{measure(c,m,f,h,d={}){let u=m/2,p=d.block||Math.max(8,Math.round(u/20)),_=Math.round(p*3),b=Math.round(p*1.5),x=null;if(o&&o.w===_&&o.h===b){let D=Mn(c,m,f,o.tpl,_,b,o.x,o.y,t,i);if(D.c>=n){let T=Je(c,m,f,D.x,D.y,_,b,{dMin:Math.floor(o.d)-e,dMax:Math.ceil(o.d)+e,dyMax:2});T&&T.c>=.8&&(x={m:T,f:D})}}let k=({m:D,f:T})=>(o={...o,x:T.x,y:T.y,d:D.d,tpl:li(c,m,T.x,T.y,_,b)},{d:D.d,x:T.x+_/2,y:T.y+b/2,c:D.c,method:"track",blocks:0});if(x&&h-o.at<s)return k(x);let w=Sn(c,m,f,d);if(x&&(!w||Math.abs(w.d-x.m.d)>r)){let D=w&&a&&Math.abs(a.d-w.d)<=3;if(a=w&&!D?{d:w.d}:null,!D)return o.at=h,k(x)}else a=null;if(!w)return o=null,null;let I=Math.round(Math.max(0,Math.min(u-_,w.x-_/2))),E=Math.round(Math.max(0,Math.min(f-b,w.y-b/2)));return o={x:I,y:E,d:w.d,tpl:li(c,m,I,E,_,b),w:_,h:b,at:h},w},reset(){o=null,a=null}}}function fi(s,e,t,i,n,r){let o=Math.max(1,r|0),a=Math.floor(i/o);a-=a&1;let l=Math.floor(n/o),c=new Uint8Array(a*l);if(o<=2){let h=o*o;for(let d=0;d<l;d++)for(let u=0;u<a;u++){let p=0;for(let _=0;_<o;_++){let b=e+(d*o+_)*t+u*o;for(let x=0;x<o;x++)p+=s[b+x]}c[d*a+u]=p/h|0}return{img:c,w:a,h:l}}let m=o>>2,f=3*o>>2;for(let h=0;h<l;h++){let d=e+(h*o+m)*t,u=e+(h*o+f)*t;for(let p=0;p<a;p++){let _=p*o+m,b=p*o+f;c[h*a+p]=s[d+_]+s[d+b]+s[u+_]+s[u+b]>>2}}return{img:c,w:a,h:l}}var U="[inline3d/call]",kn=2e3,En=2500,Cn=500,Ke=.02,Tn=4,Rn=2,Dn=200,ui=240,Ln=new Set(["I420","I420A","I422","I444","NV12"]),In="https://github.com/DisplayXR/displayxr-browser",ne=Object.freeze({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)"});function On(s={}){let e=s.ui===void 0?!0:!!s.ui,t=typeof s.tileAspect=="number"&&s.tileAspect>.3&&s.tileAspect<4?s.tileAspect:16/9,i=s.room===void 0||s.room===null?"auto":s.room;if(i!=="auto"&&!he(i)){let n=de(i);if(!n)throw new Error(`@displayxr/inline3d/call: room "${i}" is not a valid room id (16-64 base64url chars) or invite link`);i=n}return{room:i,signaling:s.signaling||Y(void 0,typeof s.key=="string"&&s.key?{key:s.key}:{}),iceServers:Array.isArray(s.iceServers)?s.iceServers:void 0,camera:s.camera===void 0?"auto":s.camera,format:s.format==="sbs"?"sbs":s.format==="mono"?"mono":void 0,calibration:s.calibration&&typeof s.calibration=="object"?{...s.calibration}:{},rectify:typeof s.rectify=="function"?s.rectify:null,audio:s.audio===void 0?!0:!!s.audio,autoConverge:s.autoConverge===void 0?!0:!!s.autoConverge,mono3D:ye(s.mono3D),maxPeers:He(s.maxPeers===void 0?J:s.maxPeers),liftOptions:s.liftOptions&&typeof s.liftOptions=="object"?{...s.liftOptions}:null,maxLifted:Number.isFinite(+s.maxLifted)&&s.maxLifted!==null?Math.max(0,Math.min(J,Math.floor(+s.maxLifted))):J,layout:s.layout==="speaker"?"speaker":"grid",ui:e,autoJoin:s.autoJoin===void 0?!e:!!s.autoJoin,selfView:s.selfView===void 0?!0:!!s.selfView,tileAspect:t,accent:typeof s.accent=="string"&&s.accent?si(s.accent):null,inviteBase:typeof s.inviteBase=="string"?s.inviteBase:null,updateUrl:s.updateUrl===void 0?e:!!s.updateUrl,browserUrl:typeof s.browserUrl=="string"?s.browserUrl:In,recoverSession:s.recoverSession===void 0?!0:!!s.recoverSession,scrollIntoView:s.scrollIntoView===void 0?!0:!!s.scrollIntoView,wallOptions:s.wallOptions&&typeof s.wallOptions=="object"?s.wallOptions:{},log:typeof s.log=="function"?s.log:s.debug?(n,r)=>console.log(`${U} ${n} ${JSON.stringify(r)}`):null,_liftImporter:typeof s._liftImporter=="function"?s._liftImporter:void 0}}async function pi(s,e,t={}){if(!e||typeof e.appendChild!="function")throw new TypeError("@displayxr/inline3d/call: addCall(wall, container, opts) needs a container element");let i=On(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 n=new Ze(s,e,i);return await n._init(),n.handle}async function Ge(s,e={}){if(!s||typeof s.appendChild!="function")throw new TypeError("@displayxr/inline3d/call: mountCall(el, opts) needs a container element");let{wall:t,...i}=e,n=t||await ce(i.wallOptions);return pi(n,s,i)}var Ze=class{constructor(e,t,i){this.o=i,this.container=t,this.wall=e||null,this.wallLive=!!(e&&e.supported),this.weaveLive=!1,this.camStatus="pending",this.id=Ot(),this.room=i.room==="auto"?de(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=Pe(Ie),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=nt(),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 n of[...i])try{n(t)}catch(r){console.error(`${U} '${e}' listener threw`,r)}}error(e,t,i){this.log("error",{code:e,message:t}),this.listeners.get("error")?.size||console.warn(`${U} ${e}: ${t}`),this.emit("error",{code:e,message:t,error:i||null})}warning(e,t){this.log("warning",{code:e,message:t}),console.warn(`${U} ${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 n=(h,d)=>this.log(h,d),r=null,o=null;try{r=await Jt(e,{format:t||this.o.format,calibration:this.o.calibration,log:n})}catch(h){o=h;let d=h.code==="camera-busy";if(this.error(d?"camera-busy":h.code||"no-camera",d?`${ne.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"}if(r&&(this.camStatus="ok"),r&&r.format==="sbs"&&this.o.rectify)try{let h=await this.o.rectify(r.stream,{width:r.width,height:r.height,deviceId:r.deviceId,label:r.label});h&&typeof h.getVideoTracks=="function"&&(r.stream=h,r.calibration={...r.calibration,rectified:!0})}catch(h){this.error("rectify-failed",`rectify() threw \u2014 sending the raw pair: ${h.message}`,h)}let a=this.local?this.local.audioTrack:null;this.o.audio&&!a&&(a=await Kt({log:n})),a&&(a.enabled=!this.muted);let l=r&&r.stream.getVideoTracks()[0]||null;if(l){try{l.contentHint="detail"}catch{}l.enabled=!this.camOff}let c=new MediaStream([l,a].filter(Boolean)),m=this.local?.video||Object.assign(document.createElement("video"),{muted:!0,playsInline:!0,autoplay:!0});m.srcObject=r?r.stream:null,m.play().catch(()=>{});let f=this.local;return this.local={stream:c,camStream:r?r.stream:null,video:m,videoTrack:l,audioTrack:a,format:r?r.format:"mono",width:r?r.width:0,height:r?r.height:0,calibration:r?r.calibration:{},owned:r?r.owned:!1,label:r?r.label:"",skipped:r?r.skipped:o?.skipped||[]},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.camStream&&f.camStream!==this.local.camStream&&f.camStream.getVideoTracks().forEach(h=>h.stop()),this._refreshSelf(),this._refreshLobby(),this.local}hello(){let e=this.local||{};return Ft({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=It(),this.log("room-created",{})),this.o.updateUrl&&globalThis.history&&globalThis.location)try{history.replaceState(history.state,"",Oe(location.href,this.room))}catch{}this._setState("joining");let e=new ue({signaling:this.o.signaling,id:this.id,maxPeers:this.o.maxPeers,iceServers:this.o.iceServers,log:(t,i)=>this.log(t,i)});this.transport=e;try{await e.start({room:this.room,localStream:this.local.stream,sendFormat:this.local.format,onPeer:t=>this._onPeer(t),onPeerLeft:(t,i)=>this._onPeerLeft(t,i),onStream:(t,i)=>this.tiles.get(t)?.setStream(i),onMessage:(t,i)=>this._onMessage(t,i),onPeerState:(t,i)=>{this.tiles.get(t)?.setConn(i),this.emit("state",{id:t,state:i})},onRefused:t=>this.log("refused-peer",{id:t}),onGhost:(t,i)=>this._onGhost(t,i),onSignalingState:(t,i)=>{this.log("signaling",{state:t}),t==="closed"&&i&&this.error(i.code||"signaling-closed",i.message,i)}})}catch(t){throw this.transport=null,t&&t.code==="room-full"?(this._setState("full"),this.error("room-full",t.message,t)):(this._setState("lobby"),this.error(t.code||"join-failed",`could not join: ${t.message}`,t)),t}if(this._setState("in-call"),this.o.ui&&this.o.scrollIntoView)try{this.container.scrollIntoView?.({block:"start",behavior:"instant"}),this._fitGrid()}catch{}return this._startStats(),this._pagehide=()=>this.leave(),globalThis.addEventListener?.("pagehide",this._pagehide),this.log("joined",{id:this.id,peers:this.tiles.size}),this.emit("joined",{room:this.room,id:this.id}),this.handle}_onPeer(e){if(this.tiles.has(e))return;let t=new ge(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 n=new ge(this,e);n.ghost=!0,this.tiles.set(e,n),n.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()},En))}_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 n=Pt(t);if(n)return i.setHello(n);let r=Ae(t);if(r)return i.setHint(r);let o=Wt(t);if(o)return i.setRemoteState(o)}inviteLink(){if(!this.room)return null;let e=this.o.inviteBase||(globalThis.location?location.href:"");return Oe(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}cameraOff(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,n=await this._openMedia(e,t,{keepOnFail:!0});return this.transport&&(await this.transport.replaceTrack("video",n.videoTrack,n.stream),await this.transport.setSendFormat(n.format),this.transport.broadcast(this.hello()),this.transport.broadcast(this.stateMsg())),i!==n.format&&this.log("send-format",{format:n.format}),{format:n.format,width:n.width,height:n.height,label:n.label}}retryCamera(){return this.setCamera(this.o.camera,{format:this.o.format})}sendHint(e){if(!this._hintGate(performance.now()))return!1;let t=Ae({type:"hint",subjectZmm:e});return t?(this.transport?.broadcast(t),!0):!1}leave(){if(this.state!=="left"){globalThis.removeEventListener?.("pagehide",this._pagehide),this.transport?.stop(),this.transport=null;for(let e of this.tiles.values())e.destroy();this.tiles.clear(),this.liftPool?.releaseAll(),clearInterval(this._statsTimer),this._setSpeaker(null),this.local&&(this.local.stream.getTracks().forEach(e=>e.stop()),this.local.owned&&this.local.camStream&&this.local.camStream.getTracks().forEach(e=>e.stop()),this.local.videoTrack=null,this.local.audioTrack=null),this.self&&(this.self.unregister(),this.self.route=null),this._unhookWall(),this._setState("left"),this._layout(),this.emit("left",{room:this.room})}}_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=(...n)=>(i.pageClosed=!0,t.apply(e,n)),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=$t(),n=performance.now(),r=(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(r)}catch{}return}this.weaveLive=!0,this.log("weave-live",{ms:Math.round(performance.now()-n)});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(r)}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.o.recoverSession||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 ce(this.o.wallOptions)}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),this.emit("session",{wall:t})},H(e,{baseMs:1e3,maxMs:15e3}))}_startLoop(){let e=0,t=i=>{this._raf=requestAnimationFrame(t),this.self?.paint();for(let n of this.tiles.values())n.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(`${U} 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=(n,r)=>this.log(n,r),t=this.o.liftOptions,i={webFallback:!0,...t&&t.models?{models:t.models}:{}};this._liftP=it(this.mono3D,{log:e,capsOpts:i,...this.o._liftImporter?{importer:this.o._liftImporter}:{}}).then(n=>(this.liftApi=n,n.lift?(this.liftPool=st({lift:n.lift,max:this.o.maxLifted,log:e,options:this.o.liftOptions}),this.liftPool.setDepth(this.depth),this.liftPool.setSpeaker(this.speakerId),!n.caps&&n.capabilities&&Promise.resolve().then(()=>n.capabilities(i)).then(r=>{n.caps=r||null,this._refreshLobby()}).catch(()=>{})):n.reason==="import-failed"||n.reason==="no-lift-export"?this.liftMissing=!0:n.reason!=="off"&&console.info(`${U} mono\u21923D unavailable (${n.reason}) \u2014 mono participants are shown flat`),this._rerouteMono(),this._refreshLobby(),n))}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"";if(!this.mono3DOn)return"Mono cameras: 2D (2D\u21923D is off).";let e=this.liftApi;if(!e)return"Mono cameras: checking 2D\u21923D\u2026";if(!e.lift)return this.liftMissing?"Mono cameras: 2D\u21923D unavailable in this build.":"Mono cameras: 2D (no 2D\u21923D provider here).";let t=e.caps;return t&&t.native?`Mono cameras: 2D\u21923D (native${t.provider?`, ${t.provider}`:""}).`:t&&t.webFallback&&t.webFallback.webgpu?"Mono cameras: 2D\u21923D (in this page, WebGPU).":this.liftProven?"Mono cameras: 2D\u21923D.":"Mono cameras: 2D\u21923D (confirmed on the first mono participant)."}_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),Cn)}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 m={};c.forEach(d=>{d.type==="codec"&&(m[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 u=a._prevIn;f.in={width:d.frameWidth||0,height:d.frameHeight||0,fps:d.framesPerSecond||0,codec:m[d.codecId]||null,kbps:u?Math.round((d.bytesReceived-u.bytes)*8/(d.timestamp-u.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 u=a._prevOut;f.out={width:d.frameWidth||0,height:d.frameHeight||0,fps:d.framesPerSecond||0,codec:m[d.codecId]||null,kbps:u?Math.round((d.bytesSent-u.bytes)*8/(d.timestamp-u.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>Ke||a.remote.speaking),h>Ke&&(!t||h>t.lvl)&&(t={id:o,lvl:h})}let n=t?t.id:null;n&&n!==this.speakerId?(this._challengeTicks=this._challenger===n?(this._challengeTicks||0)+1:1,this._challenger=n,this._challengeTicks>=2&&this._setSpeaker(n)):(this._challenger=null,this._challengeTicks=0);let r=!this.muted&&i>Ke;r!==!!this._selfSpeaking&&(this._selfSpeaking=r,this.transport?.broadcast(this.stateMsg()),this.self?.setSpeaking(r))}_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.ui||typeof globalThis.innerHeight!="number")return;let t=this.container.getBoundingClientRect?.(),i=e.grid.getBoundingClientRect?.();if(!t||!i||!i.height)return;let n=Math.max(160,Math.floor(globalThis.innerHeight-Math.max(0,t.top)-(t.height-i.height)-8)),r=parseFloat(this.container.style.getPropertyValue("--dxr-call-fit"))||0;Math.abs(n-r)>2&&this.container.style.setProperty("--dxr-call-fit",`${n}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;ri(e.ownerDocument||document),e.classList.add("dxr-call-host"),this.o.accent&&e.style.setProperty("--dxr-accent",this.o.accent);let t=this.ui={};t.banner=S("div",{class:"dxr-call-banner dxr-call-hidden"},[S("span",{text:"You are seeing this call in 2D."}),S("a",{href:this.o.browserUrl,target:"_blank",rel:"noopener",text:"View in 3D with DisplayXR Browser"})]),t.grid=S("div",{class:"dxr-call-grid","data-layout":this.o.layout,"data-n":"0"}),t.panel=S("div",{class:"dxr-call-panel dxr-call-hidden"}),t.selfSlot=S("div",{class:"dxr-call-self"}),t.bar=S("div",{class:"dxr-call-bar"}),t.foot=S("div",{class:"dxr-call-foot"},[t.selfSlot,t.bar]),t.invite=S("div",{class:"dxr-call-panel dxr-call-hidden"}),this.o.ui||O(t.bar,!1),e.append(t.banner,t.panel,t.grid,t.invite,t.foot),this.o.selfView?this.self=new Qe(this,t.selfSlot):O(t.selfSlot,!1),this.o.ui&&this._buildBar()}_buildBar(){let e=this.ui,t=(i,n,r,o="")=>S("button",{class:`dxr-call-ib ${o}`,type:"button","aria-label":i,title:i,html:n,onclick:r});e.mic=t("Mute microphone",V.mic,()=>this.mute()),e.cam=t("Turn camera off",V.cam,()=>this.local?.videoTrack?this.cameraOff():this.retryCamera().catch(()=>{})),e.depth=S("input",{type:"range",min:"-1",max:"1",step:"0.05",value:"0","aria-label":"Depth"}),e.depth.addEventListener("input",()=>this.setDepth(+e.depth.value)),e.depth.addEventListener("dblclick",()=>this.setDepth(0)),e.inviteBtn=t("Invite",V.link,()=>{this._showInvite=!this._showInvite,this._layout()}),e.leave=t("Leave call",V.leave,()=>this.leave(),"dxr-call-ib--leave"),e.bar.append(e.mic,e.cam,S("label",{class:"dxr-call-depth"},["Depth",e.depth]),e.inviteBtn,e.leave)}_refreshBar(){let e=this.ui;if(!e||!e.mic)return;e.mic.innerHTML=this.muted?V.micOff:V.mic,e.mic.setAttribute("aria-pressed",String(this.muted)),e.mic.title=this.muted?"Unmute microphone":"Mute microphone";let t=!this.local?.videoTrack;e.cam.innerHTML=this.camOff||t?V.camOff:V.cam,e.cam.setAttribute("aria-pressed",String(this.camOff||t)),e.cam.title=t?this.camStatus==="busy"?`${ne.cameraBusy} \u2014 click to retry`:"No camera \u2014 click to retry":this.camOff?"Turn camera on":"Turn camera off"}_refreshSelf(){this.self?.update()}_refreshLobby(){(this.state==="lobby"||this.state==="idle")&&this._layout()}_renderInvite(e,t,i){e.replaceChildren();let n=this.inviteLink();if(!n)return;let r=S("input",{type:"text",readOnly:!0,value:n,"aria-label":"Invite link"});r.addEventListener("focus",()=>r.select());let o=S("button",{class:"dxr-call-btn dxr-call-btn--primary",type:"button",text:"Copy link"});o.addEventListener("click",async()=>{try{await navigator.clipboard.writeText(n),o.textContent="Copied"}catch{r.select(),o.textContent="Press Ctrl/Cmd+C"}setTimeout(()=>o.textContent="Copy link",1800)});let a=S("canvas",{"aria-label":"QR code of the invite link",role:"img"});try{ti(a,n,{px:4})}catch{a.style.display="none"}e.append(S("h3",{text:t}),S("p",{text:i}),S("div",{class:"dxr-call-invite"},[S("div",{class:"dxr-call-row",style:"flex:1 1 280px"},[r,o]),a]))}_layout(){let e=this.ui;if(!e)return;let t=this.container,i=this.o.ui&&(this.state==="lobby"||this.state==="idle"||this.state==="full"||this.state==="left");t.classList.toggle("dxr-call-host--lobby",i),O(e.banner,this.o.ui&&!this.woven);let n=this.tiles.size;e.grid.dataset.n=String(Math.min(n,4)),O(e.grid,n>0&&this.state!=="left");let r=this.o.layout==="speaker"?this.speakerId||[...this.tiles.keys()][0]:null;for(let[l,c]of this.tiles)c.el.classList.toggle("dxr-call-tile--main",l===r);if(!this.o.ui)return;this._refreshBar(),queueMicrotask(()=>this._fitGrid());let o=e.panel;if(i){O(o,!0),o.replaceChildren();let l=this.local,c=!!this.room,m=this.state==="full"?"This call is full":this.state==="left"?"You left the call":c?"Join the 3D call":"Start a 3D call",f=this.camStatus==="busy"?"busy (joining audio-only)":!l||!l.videoTrack?"none (joining audio-only)":l.format==="sbs"?`sending 3D (side-by-side, ${l.width}\xD7${l.height})`:`sending 2D (${l.width}\xD7${l.height})`,h=this.state==="full"?`It already has ${this.o.maxPeers} participants.`:`Check your framing below. Camera: ${l?.label||"default"} \u2014 ${f}.${this._liftHint()?` ${this._liftHint()}`:""}`,d=S("button",{class:"dxr-call-btn dxr-call-btn--primary",type:"button",text:this.state==="left"?"Rejoin":c?"Join call":"Start 3D call"});d.addEventListener("click",()=>this.join().catch(()=>{}));let u=S("select",{class:"dxr-call-select","aria-label":"Camera"});this._fillCameras(u),u.addEventListener("change",()=>this.setCamera(u.value).catch(_=>this.error("camera-failed",_.message,_)));let p=!l||!l.videoTrack?S("button",{class:"dxr-call-btn",type:"button",text:"Retry camera"}):null;p?.addEventListener("click",()=>this.retryCamera().catch(()=>{})),o.append(S("h3",{text:m}),S("p",{text:h}),S("div",{class:"dxr-call-row"},[this.state==="full"?null:d,p,u]))}else this.state==="in-call"&&n===0?(O(o,!0),this._renderInvite(o,"Waiting for others","Share this link (or scan the code). Anyone who opens it joins \u2014 keep it private.")):this.state==="joining"?(O(o,!0),o.replaceChildren(S("p",{text:"Joining\u2026"}))):O(o,!1);let a=this.state==="in-call"&&n>0&&this._showInvite;a&&!e.invite.childElementCount&&this._renderInvite(e.invite,"Invite","Anyone with this link can join."),O(e.invite,a),a||e.invite.replaceChildren(),e.inviteBtn?.setAttribute("aria-pressed",String(!!a))}async _fillCameras(e){let t=[];try{t=(await navigator.mediaDevices.enumerateDevices()).filter(n=>n.kind==="videoinput")}catch{}let i=this.local?.videoTrack?.getSettings?.().deviceId;e.replaceChildren(...t.map((n,r)=>S("option",{value:n.deviceId,text:n.label||`Camera ${r+1}`}))),i&&(e.value=i),O(e,t.length>1)}_makeHandle(){let e=this;return{get room(){return e.room},get id(){return e.id},get state(){return e.state},get wall(){return e.wall},get format(){return e.local?e.local.format:null},get muted(){return e.muted},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(t=>t.info()))},join:()=>e.join(),inviteLink:()=>e.inviteLink(),mute:t=>e.mute(t),cameraOff:t=>e.cameraOff(t),setCamera:(t,i)=>e.setCamera(t,i),setDepth:t=>e.setDepth(t),retryCamera:()=>e.retryCamera(),sendHint:t=>e.sendHint(t),setMono3D:t=>e.setMono3D(t),leave:()=>e.leave(),on(t,i){if(typeof i!="function")throw new TypeError(`${U} on() takes a function`);return e.listeners.has(t)||e.listeners.set(t,new Set),e.listeners.get(t).add(i),()=>e.listeners.get(t)?.delete(i)},off(t,i){e.listeners.get(t)?.delete(i)},_debug:{get transport(){return e.transport},kill:t=>e.transport?._debugKill(t)}}}};function An(s){let e=Math.min(globalThis.devicePixelRatio||1,2),t=Math.round((s.clientWidth||0)*e),i=Math.round((s.clientHeight||0)*e);return!t||!i?!1:((s.width!==t||s.height!==i)&&(s.width=t,s.height=i),!0)}function Ye(s,e,{eyeHalf:t=null,mirror:i=!1}={}){if(!An(s))return;let n=s.getContext("2d"),r=e.videoWidth,o=e.videoHeight;if(!r||!o||(e.readyState||0)<2)return;let a=t===null?r:r/2,l=fe(a,o,s.width/s.height,0,0);n.save(),i&&(n.translate(s.width,0),n.scale(-1,1)),n.drawImage(e,(t||0)*a+l.sx,l.sy,l.sw,l.sh,0,0,s.width,s.height),n.restore()}var ge=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=Vt(),this.autoTrack=hi(),this.autoFocus=di(),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=Pe(Ie),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=S("canvas"),this.cover=S("div",{class:"dxr-call-cover dxr-call-hidden"}),this.badge=S("div",{class:"dxr-call-badge"}),this.plate=S("div",{class:"dxr-call-state",text:"Connecting\u2026"}),this.stage=S("div",{class:"dxr-call-stage"},[this.canvas,this.cover,this.badge,this.plate]),this.stage.style.aspectRatio=String(e.o.tileAspect),this.el=S("div",{class:"dxr-call-tile","data-peer":t},[this.stage,S("div",{class:"dxr-call-talk"})]),e.o.ui||O(this.badge,!1),e.ui.grid.appendChild(this.el),this._renderBadge()}info(){return Object.freeze({id:this.id,format:this.format||"mono",route:this.route,state:this.conn,muted:this.remote.muted,cameraOff:this.remote.cameraOff,speaking:this.speaking,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?Object.freeze({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})}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())},kn)}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",`${ne.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.conn==="left"?"Left the call":this.conn==="unreachable"?ne.unreachable:this.conn==="reconnecting"?"Reconnecting\u2026":this.conn!=="connected"?"Connecting\u2026":this.remote.cameraOff?"Camera off":null;this.plate.textContent=e||"",O(this.plate,!!e)}_renderBadge(){let e=Ht(this.route),t=this.route?this.route==="lifted"&&!this.liftLive?`${e}\u2026`:e:"\u2026";this.badge.replaceChildren(S("b",{text:t})),this.badge.dataset.route=this.route||"",this.remote.muted&&this.badge.insertAdjacentHTML("beforeend",V.mutedSmall)}_maybeRoute(){!this.format||(this.video.readyState||0)<2||!this.video.videoWidth||this.reroute(!1)}reroute(e){let t=this.call,i=t.liftPool,n=this.forceFlat&&this.format==="sbs"?{route:"flat-left"}:Nt({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 r=`${n.route}|${this.format}`;!e&&r===this.routedKey||(this.routedKey=r,this._unregister(),this.route=n.route,n.route==="woven-sbs"?this._registerWoven():n.route==="lifted"&&this._registerLifted(),t.log("route",{peer:this.id,route:n.route,format:this.format,mono3d:n.mono3d||null}),t.emit("format",{id:this.id,format:this.format,route:n.route,mono3d:n.mono3d||null,hello:this.hello}),this._renderBadge())}_registerWoven(){let e=this.call;this.convCanvas||(this.convCanvas=document.createElement("canvas")),this._paintConv(),O(this.cover,!0);let t=e.wall.addImage(this.canvas,this.convCanvas);this.handle=t,t.firstWoven?.then(i=>{this.handle===t&&(O(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 n=r=>{r==="live"?this._liftShowing(!0):(r==="error"||r==="disposed")&&this._liftShowing(!1)};this._liftOff=[i.on?.("statechange",r=>n(r&&r.state)),i.on?.("error",r=>{r&&r.fatal&&this._liftError(r.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++>=Rn)&&(clearTimeout(this.liftTimer),this.liftTimer=setTimeout(()=>{this.liftFailed=!1,this.reroute(!1)},H(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++>=Tn)return;let e=H(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(O(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||Ye(this.canvas,this.video):Ye(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 n=t/2,r=this.call.o.tileAspect,{w:o,h:a}=Fe(n,i,r),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(n),m=l.getContext("2d");for(let f of[0,1]){let h=fe(n,i,r,c,f);m.drawImage(e,f*n+h.sx,h.sy,h.sw,h.sh,f*o,0,o,a)}}_sampleDisparity(e,t,i){let n=performance.now();if(this.autoPending||n-this.autoAt<Dn)return;if(this.autoAt=n,typeof VideoFrame=="function"){let f=null;try{f=new VideoFrame(e)}catch{f=null}if(f&&Ln.has(f.format)){this.autoPending=!0;let h=this.autoGen,d=f.visibleRect?f.visibleRect.width:f.displayWidth,u=f.visibleRect?f.visibleRect.height:f.displayHeight,p=new Uint8Array(f.allocationSize());f.copyTo(p).then(_=>{if(h!==this.autoGen)return;let b=performance.now(),x=Math.max(1,Math.ceil(d/2/ui)),k=fi(p,_[0].offset,_[0].stride,d,u,x);this._applyMeasurement(k.img,k.w,k.h,k.w/d,n,performance.now()-b,"videoframe")}).catch(()=>{h===this.autoGen&&this._applyMeasurement(null,0,0,1,n,0,"videoframe")}).finally(()=>{f.close(),this.autoPending=!1});return}f&&f.close()}let r=Math.min(1,ui/(t/2)),o=Math.max(2,Math.round(t*r/2)*2),a=Math.max(2,Math.round(i*r));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}),m=null;try{c.drawImage(e,0,0,o,a),m=ci(c.getImageData(0,0,o,a).data,o*a)}catch{m=null}this._applyMeasurement(m,o,a,o/t,n,performance.now()-n,"canvas")}_applyMeasurement(e,t,i,n,r,o,a){if(this.destroyed)return;let l=performance.now(),c=e?this.autoFocus.measure(e,t,i,r):null,m=this.autoTrack.push(c?c.d/n:null);this.conv.measuredPx=m,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(m*10)/10,at:{x:Math.round(c.x/n),y:Math.round(c.y/n)},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()}},Qe=class{constructor(e,t){this.call=e,this.canvas=S("canvas"),this.badge=S("div",{class:"dxr-call-badge"}),this.plate=S("div",{class:"dxr-call-state dxr-call-hidden"}),this.stage=S("div",{class:"dxr-call-stage"},[this.canvas,this.badge,this.plate]),this.stage.style.aspectRatio=String(e.o.tileAspect),this.el=S("div",{class:"dxr-call-tile dxr-call-tile--self"},[this.stage,S("div",{class:"dxr-call-talk"})]),t.appendChild(this.el),this.route=null,this.handle=null,this.mirror=null}update(){let e=this.call.local,t=!e||!e.videoTrack;this.plate.textContent=t?this.call.camStatus==="busy"?ne.cameraBusy:this.call.camStatus==="pending"?"":"No camera":this.call.camOff?"Camera off":"",O(this.plate,t||this.call.camOff),this.reroute(!1)}reroute(e){let t=this.call.local,i=t&&t.format==="sbs"&&this.call.woven&&t.videoTrack?"woven-sbs":t&&t.format==="sbs"?"flat-left":"flat";if(!e&&i===this.route)return this._badge();this.unregister(),this.route=i,i==="woven-sbs"&&(this.mirror||(this.mirror=document.createElement("canvas")),this._paintMirror(),this.handle=this.call.wall.addImage(this.canvas,this.mirror)),this._badge()}_badge(){this.badge.replaceChildren(S("b",{text:`You \xB7 ${this.route==="woven-sbs"?"3D":"2D"}`}))}onWallLost(){this.handle=null,this.reroute(!0)}unregister(){if(this.handle){try{this.handle.remove()}catch{}this.handle=null}}setSpeaking(e){this.el.classList.toggle("dxr-call-tile--speaking",e)}paint(){let e=this.call.local;!e||!e.video||this.call.state==="left"||(this.route==="woven-sbs"?this._paintMirror():Ye(this.canvas,e.video,{eyeHalf:this.route==="flat-left"?0:null,mirror:!0}))}_paintMirror(){let e=this.call.local.video,t=e.videoWidth,i=e.videoHeight;if(!t||!i||(e.readyState||0)<2)return;let n=this.call.o.tileAspect,r=t/2,{w:o,h:a}=Fe(r,i,n),l=this.mirror;(l.width!==2*o||l.height!==a)&&(l.width=2*o,l.height=a);let c=l.getContext("2d"),m=fe(r,i,n,0,0);for(let f of zt(t,i)){let h=f.dx===0?0:o;c.save(),c.translate(h+o,0),c.scale(-1,1),c.drawImage(e,f.sx+m.sx,m.sy,m.sw,m.sh,0,0,o,a),c.restore()}}};pe();tt(()=>new URL("./lift.js",import.meta.url).href);export{je as CALL_EVENT_PREFIX,Xe as DXR_SIGNAL_DEFAULT,Z as DxrCallElement,pi as addCall,qe as attrsToOpts,Ct as createInline3D,pe as defineCallElement,Y as dxrSignaling,kt as inline3DAvailable,Ge as mountCall,de as parseInviteLink,ce as sharedInline3D};
|
package/index.d.ts
CHANGED
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
/** Options shared by every add*() call. */
|
|
5
5
|
export interface TileOptions {
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Per-eye buffer resolution in px (defaults to the CSS box × devicePixelRatio, dpr capped at 2).
|
|
8
|
+
* `addImage` / `addVideo` clamp the store to the device's GL limits — 2 × width and the height
|
|
9
|
+
* within min(MAX_TEXTURE_SIZE, MAX_RENDERBUFFER_SIZE, MAX_VIEWPORT_DIMS), both axes by one
|
|
10
|
+
* factor, warned once — explicit sizes included. An `addScene` canvas is the page's to size;
|
|
11
|
+
* the SDK warns once if the browser clamped its drawing buffer below `canvas.width/height`.
|
|
12
|
+
*/
|
|
7
13
|
width?: number;
|
|
8
14
|
/** Per-eye buffer height in px (see `width`). */
|
|
9
15
|
height?: number;
|
|
@@ -25,6 +31,8 @@ export interface TileOptions {
|
|
|
25
31
|
*
|
|
26
32
|
* - `woven: true, reason: 'hold-elapsed'` — a stereo frame is on a layer that has existed for
|
|
27
33
|
* `firstWovenHoldMs`. Drop the poster covering the canvas.
|
|
34
|
+
* - `woven: true, reason: 'hold-capped'` — `rewoven()` only: the canvas kept resizing, so it
|
|
35
|
+
* stopped waiting four holds after the call. Drop the cover; the rect may still be settling.
|
|
28
36
|
* - `woven: false` — the window will not weave (`'layer-failed'`, `'session-ended'`,
|
|
29
37
|
* `'removed'`; the subpaths add `'unsupported'`). The canvas is already flat (image/video) or
|
|
30
38
|
* its `onLayerLost` has run (scene). Drop the poster onto the 2D fallback.
|
|
@@ -36,7 +44,7 @@ export interface FirstWovenResult {
|
|
|
36
44
|
* that, so the result is the SDK's worst-case hold rather than a report.
|
|
37
45
|
*/
|
|
38
46
|
readonly confirmed: boolean;
|
|
39
|
-
readonly reason: 'hold-elapsed' | 'layer-failed' | 'session-ended' | 'removed' | 'unsupported';
|
|
47
|
+
readonly reason: 'hold-elapsed' | 'hold-capped' | 'layer-failed' | 'session-ended' | 'removed' | 'unsupported';
|
|
40
48
|
/** Milliseconds from the add*() call to settling. */
|
|
41
49
|
readonly ms: number;
|
|
42
50
|
}
|
|
@@ -378,6 +386,16 @@ export interface TileHandle {
|
|
|
378
386
|
readonly firstWoven: Promise<FirstWovenResult>;
|
|
379
387
|
/** Callback form of {@link TileHandle.firstWoven}: called once, asynchronously. Returns an unsubscribe. */
|
|
380
388
|
onFirstWoven(cb: (result: FirstWovenResult) => void): () => void;
|
|
389
|
+
/**
|
|
390
|
+
* {@link TileHandle.firstWoven}, measured from NOW. Cover an already-woven canvas across a rect
|
|
391
|
+
* change (fullscreen, a layout resize), then release on this. A change of the canvas's CSS size
|
|
392
|
+
* or devicePixelRatio while pending restarts the hold (checked every frame, any window kind; a
|
|
393
|
+
* move without a resize is not detected). It settles anyway, `woven: true, reason:
|
|
394
|
+
* 'hold-capped'`, four holds after the call, so a size that never stops animating cannot hold a
|
|
395
|
+
* cover up for good. A second call while pending returns the same promise, restarted. Before the
|
|
396
|
+
* first join it is `firstWoven`; on a window that will not weave it is that `woven: false` result.
|
|
397
|
+
*/
|
|
398
|
+
rewoven(): Promise<FirstWovenResult>;
|
|
381
399
|
}
|
|
382
400
|
|
|
383
401
|
/** An open inline-3D session you add weaved windows to. Returned by {@link createInline3D}. */
|
|
@@ -672,6 +690,20 @@ export function createInline3D(
|
|
|
672
690
|
opts?: CreateInline3DOptions,
|
|
673
691
|
): Promise<Inline3D | Inline3DUnsupported>;
|
|
674
692
|
|
|
693
|
+
/**
|
|
694
|
+
* The document's shared manager: the live {@link createInline3D} result if one exists, else a new
|
|
695
|
+
* one. One inline-3D session per document (woven-canvas rule 1) is the point: a module that needs
|
|
696
|
+
* a wall it did not create (`mountCall`, `<dxr-call>`) uses this instead of opening a second
|
|
697
|
+
* session, and a page that made its own wall first gets that same wall back here.
|
|
698
|
+
*
|
|
699
|
+
* `opts` apply only when this call creates the manager. An unsupported browser resolves to
|
|
700
|
+
* `{ supported: false }` every time (nothing is cached; a later call re-probes). Two callers
|
|
701
|
+
* racing before the first session resolves share one creation. Additive since 1.29.
|
|
702
|
+
*/
|
|
703
|
+
export function sharedInline3D(
|
|
704
|
+
opts?: CreateInline3DOptions,
|
|
705
|
+
): Promise<Inline3D | Inline3DUnsupported>;
|
|
706
|
+
|
|
675
707
|
/**
|
|
676
708
|
* Back-compatible single-scene helper: open a session, weave one canvas, drive a render callback
|
|
677
709
|
* each frame. Equivalent to `createInline3D({lazy:false})` then `addScene(canvas, onFrame)`.
|