three-vr-player 0.3.0 → 0.5.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/README.md +3 -0
- package/dist/Player.d.ts +6 -1
- package/dist/{VideoSource-CJGIX8gL.js → VideoSource-BGaVaGUn.js} +2 -2
- package/dist/VideoSource-BGaVaGUn.js.map +1 -0
- package/dist/core.js +1 -1
- package/dist/three-vr-player.js +185 -155
- package/dist/three-vr-player.js.map +1 -1
- package/dist/three-vr-player.standalone.js +18 -18
- package/dist/three-vr-player.standalone.js.map +1 -1
- package/dist/ui/ControlsUI.d.ts +2 -2
- package/package.json +1 -1
- package/dist/VideoSource-CJGIX8gL.js.map +0 -1
package/README.md
CHANGED
|
@@ -62,6 +62,9 @@ menu in the controls, or set it programmatically:
|
|
|
62
62
|
| `flat-sbs-full` | flat screen | left/right (full-width per eye) |
|
|
63
63
|
| `flat-sbs-half` | flat screen | left/right (half-width per eye) |
|
|
64
64
|
|
|
65
|
+
Pick **Off (native player)** in the menu — or call `setProjection('off')` — to disable
|
|
66
|
+
reprojection and play the raw **2D `<video>`** (the same view as the CORS fallback).
|
|
67
|
+
|
|
65
68
|
## Options
|
|
66
69
|
|
|
67
70
|
```ts
|
package/dist/Player.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export declare class Player {
|
|
|
17
17
|
private view;
|
|
18
18
|
private readyEmitted;
|
|
19
19
|
private native;
|
|
20
|
+
private tainted;
|
|
21
|
+
private displayMode;
|
|
20
22
|
private loading;
|
|
21
23
|
private proxyConfig?;
|
|
22
24
|
private useProxy;
|
|
@@ -30,7 +32,10 @@ export declare class Player {
|
|
|
30
32
|
private setNativeFallback;
|
|
31
33
|
play(): Promise<void>;
|
|
32
34
|
pause(): void;
|
|
33
|
-
|
|
35
|
+
/** Set the display mode: a geometry projection (WebGL 3D) or 'off' for plain 2D `<video>`. */
|
|
36
|
+
setProjection(p: Projection | 'off'): void;
|
|
37
|
+
private applyProjectionGeometry;
|
|
38
|
+
private applyDisplay;
|
|
34
39
|
setSwapEyes(v: boolean): void;
|
|
35
40
|
setFov(deg: number): void;
|
|
36
41
|
setSupersampling(x: number): void;
|
|
@@ -38,7 +38,7 @@ const h = {
|
|
|
38
38
|
{ value: "360-mono", label: "360° Mono" },
|
|
39
39
|
{ value: "360-sbs", label: "360° SBS" },
|
|
40
40
|
{ value: "360-tb", label: "360° Top-Bottom" },
|
|
41
|
-
{ value: "flat-2d", label: "Flat 2D
|
|
41
|
+
{ value: "flat-2d", label: "Flat 2D" },
|
|
42
42
|
{ value: "flat-sbs-full", label: "Flat 3D — Full SBS" },
|
|
43
43
|
{ value: "flat-sbs-half", label: "Flat 3D — Half SBS" }
|
|
44
44
|
];
|
|
@@ -245,4 +245,4 @@ export {
|
|
|
245
245
|
M as d,
|
|
246
246
|
R as i
|
|
247
247
|
};
|
|
248
|
-
//# sourceMappingURL=VideoSource-
|
|
248
|
+
//# sourceMappingURL=VideoSource-BGaVaGUn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoSource-BGaVaGUn.js","sources":["../src/core/proxy.ts","../src/core/projections.ts","../src/core/StereoScene.ts","../src/core/LookControls.ts","../src/core/VideoSource.ts"],"sourcesContent":["export type StreamFormat = 'hls' | 'dash' | 'progressive';\r\n\r\nexport interface ProxyConfig {\r\n url: string;\r\n apiPassword?: string;\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/** Detect streaming format from a URL by extension. */\r\nexport function detectFormat(rawUrl: string): StreamFormat {\r\n let pathname = rawUrl;\r\n try { pathname = new URL(rawUrl).pathname; } catch { /* relative/opaque: use raw */ }\r\n const lower = pathname.toLowerCase();\r\n if (lower.endsWith('.m3u8')) return 'hls';\r\n if (lower.endsWith('.mpd')) return 'dash';\r\n return 'progressive';\r\n}\r\n\r\nconst ENDPOINTS: Record<StreamFormat, string> = {\r\n progressive: '/proxy/stream',\r\n hls: '/proxy/hls/manifest.m3u8',\r\n dash: '/proxy/mpd/manifest.m3u8',\r\n};\r\n\r\n/**\r\n * Build the URL the `<video>`/hls.js should load. When `proxy` is omitted the raw\r\n * URL is returned (it must then be CORS-clean to be used as a WebGL texture).\r\n */\r\nexport function buildProxyUrl(rawUrl: string, proxy?: ProxyConfig): { url: string; format: StreamFormat } {\r\n const format = detectFormat(rawUrl);\r\n if (!proxy || !proxy.url) return { url: rawUrl, format };\r\n const base = proxy.url.replace(/\\/+$/, '');\r\n const params = new URLSearchParams();\r\n params.set('d', rawUrl);\r\n if (proxy.apiPassword) params.set('api_password', proxy.apiPassword);\r\n for (const [name, value] of Object.entries(proxy.headers ?? {})) {\r\n if (value != null && value !== '') params.set(`h_${name}`, value);\r\n }\r\n return { url: `${base}${ENDPOINTS[format]}?${params.toString()}`, format };\r\n}\r\n","import type { Projection } from '../types.js';\r\n\r\nexport type Split = 'mono' | 'sbs' | 'tb';\r\nexport type GeomKind = 'sphere180' | 'sphere360' | 'plane';\r\n\r\nexport interface ModeConfig {\r\n geom: GeomKind;\r\n split: Split;\r\n stereo: boolean;\r\n flat?: boolean;\r\n /** plane only: 'full' = displayW/H, 'per-eye' = (W/2)/H */\r\n aspect?: 'full' | 'per-eye';\r\n}\r\n\r\nexport const MODES: Record<Projection, ModeConfig> = {\r\n '180-sbs': { geom: 'sphere180', split: 'sbs', stereo: true },\r\n '180-mono': { geom: 'sphere180', split: 'mono', stereo: false },\r\n '360-mono': { geom: 'sphere360', split: 'mono', stereo: false },\r\n '360-sbs': { geom: 'sphere360', split: 'sbs', stereo: true },\r\n '360-tb': { geom: 'sphere360', split: 'tb', stereo: true },\r\n 'flat-2d': { geom: 'plane', split: 'mono', stereo: false, flat: true, aspect: 'full' },\r\n 'flat-sbs-full': { geom: 'plane', split: 'sbs', stereo: true, flat: true, aspect: 'per-eye' },\r\n 'flat-sbs-half': { geom: 'plane', split: 'sbs', stereo: true, flat: true, aspect: 'full' },\r\n};\r\n\r\nexport const PROJECTIONS: { value: Projection; label: string }[] = [\r\n { value: '180-sbs', label: '180° SBS (VR180)' },\r\n { value: '180-mono', label: '180° Mono' },\r\n { value: '360-mono', label: '360° Mono' },\r\n { value: '360-sbs', label: '360° SBS' },\r\n { value: '360-tb', label: '360° Top-Bottom' },\r\n { value: 'flat-2d', label: 'Flat 2D' },\r\n { value: 'flat-sbs-full', label: 'Flat 3D — Full SBS' },\r\n { value: 'flat-sbs-half', label: 'Flat 3D — Half SBS' },\r\n];\r\n\r\nexport function isFlatMode(p: Projection): boolean {\r\n return !!MODES[p]?.flat;\r\n}\r\n\r\n/** Guess a projection from a URL / filename; null when nothing recognizable. */\r\nexport function detectProjection(url: string): Projection | null {\r\n const s = String(url).toLowerCase();\r\n const tb = /(^|[^a-z])(tb|ou|top.?bottom|over.?under)([^a-z]|$)/.test(s);\r\n const sbs = /(sbs|side.?by.?side)/.test(s);\r\n if (s.includes('360')) {\r\n if (tb) return '360-tb';\r\n if (sbs) return '360-sbs';\r\n return '360-mono';\r\n }\r\n if (s.includes('180') || s.includes('vr180')) {\r\n return s.includes('mono') ? '180-mono' : '180-sbs';\r\n }\r\n if (sbs) return s.includes('half') ? 'flat-sbs-half' : 'flat-sbs-full';\r\n return null;\r\n}\r\n","import * as THREE from 'three';\r\nimport { VRButton } from 'three/examples/jsm/webxr/VRButton.js';\r\nimport type { Projection } from '../types.js';\r\nimport { MODES } from './projections.js';\r\n\r\n/**\r\n * Maps a video onto the geometry for a chosen projection (inside-out 180/360\r\n * sphere or a flat screen plane) and packs stereo eyes via UV split + WebXR\r\n * layers. Sizes to its canvas's container (not the window), for embedding.\r\n */\r\nexport class StereoScene {\r\n readonly renderer: THREE.WebGLRenderer;\r\n readonly scene = new THREE.Scene();\r\n readonly camera: THREE.PerspectiveCamera;\r\n readonly vrButton: HTMLElement;\r\n readonly maxAnisotropy: number;\r\n\r\n private readonly canvas: HTMLCanvasElement;\r\n private readonly video: HTMLVideoElement;\r\n private readonly texture: THREE.VideoTexture;\r\n private readonly meshes: THREE.Mesh[] = [];\r\n private readonly frameCbs: (() => void)[] = [];\r\n private readonly animate = () => {\r\n for (const cb of this.frameCbs) cb();\r\n this.renderer.render(this.scene, this.camera);\r\n };\r\n private readonly ro: ResizeObserver;\r\n private currentMode: Projection;\r\n private currentSwap: boolean;\r\n\r\n constructor(opts: {\r\n canvas: HTMLCanvasElement; video: HTMLVideoElement;\r\n projection?: Projection; swapEyes?: boolean; fov?: number; supersampling?: number;\r\n }) {\r\n const { canvas, video, projection = '180-sbs', swapEyes = false, fov = 70, supersampling = 1.5 } = opts;\r\n this.canvas = canvas;\r\n this.video = video;\r\n this.currentMode = MODES[projection] ? projection : '180-sbs';\r\n this.currentSwap = swapEyes;\r\n\r\n this.renderer = new THREE.WebGLRenderer({ canvas, antialias: true });\r\n this.renderer.setPixelRatio(this.pixelRatioFor(supersampling));\r\n this.renderer.setSize(this.w(), this.h(), false);\r\n this.renderer.xr.enabled = true;\r\n\r\n this.camera = new THREE.PerspectiveCamera(fov, this.w() / this.h(), 0.1, 1000);\r\n this.camera.position.set(0, 0, 0);\r\n this.camera.layers.enable(1); // desktop shows Layer 1 (left eye) for stereo modes\r\n\r\n this.maxAnisotropy = this.renderer.capabilities.getMaxAnisotropy();\r\n this.texture = new THREE.VideoTexture(video);\r\n this.texture.colorSpace = THREE.SRGBColorSpace;\r\n this.texture.minFilter = THREE.LinearFilter;\r\n this.texture.magFilter = THREE.LinearFilter;\r\n this.texture.anisotropy = this.maxAnisotropy;\r\n\r\n this.applyProjection(this.currentMode, this.currentSwap);\r\n video.addEventListener('loadedmetadata', () => {\r\n if (MODES[this.currentMode].flat) this.applyProjection(this.currentMode, this.currentSwap);\r\n });\r\n\r\n this.renderer.setAnimationLoop(this.animate);\r\n this.vrButton = VRButton.createButton(this.renderer);\r\n\r\n this.ro = new ResizeObserver(() => this.resize());\r\n this.ro.observe(canvas);\r\n }\r\n\r\n private w() { return this.canvas.clientWidth || 1; }\r\n private h() { return this.canvas.clientHeight || 1; }\r\n private pixelRatioFor(ss: number) { return Math.min(window.devicePixelRatio * ss, 4); }\r\n\r\n private planeAspect(mode: Projection) {\r\n const vw = this.video.videoWidth, vh = this.video.videoHeight;\r\n if (!vw || !vh) return 16 / 9;\r\n return MODES[mode].aspect === 'per-eye' ? (vw / 2) / vh : vw / vh;\r\n }\r\n\r\n private buildGeometry(mode: Projection): THREE.BufferGeometry {\r\n const kind = MODES[mode].geom;\r\n if (kind === 'sphere180') { const g = new THREE.SphereGeometry(500, 60, 40, -Math.PI, Math.PI, 0, Math.PI); g.scale(-1, 1, 1); return g; }\r\n if (kind === 'sphere360') { const g = new THREE.SphereGeometry(500, 60, 40); g.scale(-1, 1, 1); return g; }\r\n const h = 2.4, w = h * this.planeAspect(mode);\r\n const g = new THREE.PlaneGeometry(w, h); g.translate(0, 0, -2); return g;\r\n }\r\n\r\n private splitUV(geo: THREE.BufferGeometry, split: string, eye: 'left' | 'right') {\r\n if (split === 'mono') return;\r\n const uv = geo.attributes.uv.array as Float32Array;\r\n for (let i = 0; i < uv.length; i += 2) {\r\n if (split === 'sbs') uv[i] = uv[i] * 0.5 + (eye === 'right' ? 0.5 : 0);\r\n else if (split === 'tb') uv[i + 1] = uv[i + 1] * 0.5 + (eye === 'left' ? 0.5 : 0); // top = left\r\n }\r\n geo.attributes.uv.needsUpdate = true;\r\n }\r\n\r\n private clearMeshes() {\r\n for (const m of this.meshes) { this.scene.remove(m); m.geometry.dispose(); (m.material as THREE.Material).dispose(); }\r\n this.meshes.length = 0;\r\n }\r\n\r\n private applyProjection(mode: Projection, swap: boolean) {\r\n if (!MODES[mode]) mode = '180-sbs';\r\n this.clearMeshes();\r\n const cfg = MODES[mode];\r\n if (!cfg.stereo) {\r\n const m = new THREE.Mesh(this.buildGeometry(mode), new THREE.MeshBasicMaterial({ map: this.texture }));\r\n m.layers.set(0); // mono: desktop + both XR eyes\r\n this.scene.add(m); this.meshes.push(m);\r\n } else {\r\n const gL = this.buildGeometry(mode); this.splitUV(gL, cfg.split, 'left');\r\n const gR = this.buildGeometry(mode); this.splitUV(gR, cfg.split, 'right');\r\n const mL = new THREE.Mesh(gL, new THREE.MeshBasicMaterial({ map: this.texture }));\r\n const mR = new THREE.Mesh(gR, new THREE.MeshBasicMaterial({ map: this.texture }));\r\n mL.layers.set(swap ? 2 : 1); mR.layers.set(swap ? 1 : 2);\r\n this.scene.add(mL, mR); this.meshes.push(mL, mR);\r\n }\r\n this.currentMode = mode; this.currentSwap = swap;\r\n }\r\n\r\n setProjection(p: Projection) { this.applyProjection(p, this.currentSwap); }\r\n setSwapEyes(v: boolean) { this.applyProjection(this.currentMode, v); }\r\n setFov(deg: number) { this.camera.fov = deg; this.camera.updateProjectionMatrix(); }\r\n setSupersampling(ss: number) { this.renderer.setPixelRatio(this.pixelRatioFor(ss)); this.renderer.setSize(this.w(), this.h(), false); }\r\n getProjection() { return this.currentMode; }\r\n isFlat() { return !!MODES[this.currentMode].flat; }\r\n onFrame(cb: () => void) { this.frameCbs.push(cb); }\r\n pauseRendering() { this.renderer.setAnimationLoop(null); }\r\n resumeRendering() { this.renderer.setAnimationLoop(this.animate); }\r\n\r\n resize = () => {\r\n const w = this.w(), h = this.h();\r\n this.camera.aspect = w / h;\r\n this.camera.updateProjectionMatrix();\r\n this.renderer.setSize(w, h, false);\r\n };\r\n\r\n dispose() {\r\n this.ro.disconnect();\r\n this.renderer.setAnimationLoop(null);\r\n this.texture.dispose();\r\n this.clearMeshes();\r\n this.renderer.dispose();\r\n }\r\n}\r\n","import type { Camera } from 'three';\r\n\r\nconst DEG = Math.PI / 180;\r\n\r\n/** Clamp look angles (degrees) to keep the view inside the front hemisphere. */\r\nexport function clampAngles(lon: number, lat: number): { lon: number; lat: number } {\r\n return {\r\n lon: Math.max(-90, Math.min(90, lon)),\r\n lat: Math.max(-85, Math.min(85, lat)),\r\n };\r\n}\r\n\r\n/**\r\n * Pointer/touch drag → camera yaw/pitch, clamped to the front hemisphere.\r\n * Disabled while an XR session drives the head pose, and for flat-screen modes.\r\n */\r\nexport class LookControls {\r\n private lon = 0;\r\n private lat = 0;\r\n private dragging = false;\r\n private px = 0;\r\n private py = 0;\r\n private enabled = true;\r\n private readonly isPresenting: () => boolean;\r\n\r\n constructor(\r\n private readonly camera: Camera,\r\n private readonly dom: HTMLElement,\r\n opts: { isPresenting?: () => boolean } = {},\r\n ) {\r\n this.isPresenting = opts.isPresenting ?? (() => false);\r\n this.dom.addEventListener('pointerdown', this.onDown);\r\n this.dom.addEventListener('pointermove', this.onMove);\r\n this.dom.addEventListener('pointerup', this.onUp);\r\n this.dom.addEventListener('pointercancel', this.onUp);\r\n }\r\n\r\n private capture(fn: 'setPointerCapture' | 'releasePointerCapture', id: number) {\r\n try { this.dom[fn]?.(id); } catch { /* pointer not active */ }\r\n }\r\n\r\n private onDown = (e: PointerEvent) => {\r\n if (!this.enabled) return;\r\n this.dragging = true;\r\n this.px = e.clientX;\r\n this.py = e.clientY;\r\n this.capture('setPointerCapture', e.pointerId);\r\n };\r\n\r\n private onMove = (e: PointerEvent) => {\r\n if (!this.dragging) return;\r\n const dx = e.clientX - this.px;\r\n const dy = e.clientY - this.py;\r\n this.px = e.clientX;\r\n this.py = e.clientY;\r\n ({ lon: this.lon, lat: this.lat } = clampAngles(this.lon - dx * 0.15, this.lat + dy * 0.15));\r\n };\r\n\r\n private onUp = (e: PointerEvent) => {\r\n this.dragging = false;\r\n this.capture('releasePointerCapture', e.pointerId);\r\n };\r\n\r\n update() {\r\n if (this.isPresenting() || !this.enabled) return;\r\n const phi = (90 - this.lat) * DEG;\r\n const theta = this.lon * DEG;\r\n this.camera.lookAt(\r\n Math.sin(phi) * Math.sin(theta),\r\n Math.cos(phi),\r\n -Math.sin(phi) * Math.cos(theta),\r\n );\r\n }\r\n\r\n reset() { this.lon = 0; this.lat = 0; }\r\n\r\n setEnabled(v: boolean) {\r\n this.enabled = v;\r\n if (!v) { this.lon = 0; this.lat = 0; this.camera.lookAt(0, 0, -1); }\r\n }\r\n\r\n getAngles() { return { lon: this.lon, lat: this.lat }; }\r\n\r\n dispose() {\r\n this.dom.removeEventListener('pointerdown', this.onDown);\r\n this.dom.removeEventListener('pointermove', this.onMove);\r\n this.dom.removeEventListener('pointerup', this.onUp);\r\n this.dom.removeEventListener('pointercancel', this.onUp);\r\n }\r\n}\r\n","import type Hls from 'hls.js';\r\nimport type { StreamFormat } from './proxy.js';\r\n\r\n/**\r\n * Attaches a source to a `<video>`. Progressive files go straight on `video.src`;\r\n * HLS/DASH-as-HLS go through hls.js — which is imported dynamically, so consumers\r\n * who never play HLS don't pay for it (and it's an optional dependency).\r\n */\r\nexport class VideoSource {\r\n private hls: Hls | null = null;\r\n\r\n async attach(\r\n video: HTMLVideoElement,\r\n source: { url: string; format: StreamFormat },\r\n opts: { crossOrigin?: string | null } = {},\r\n ): Promise<void> {\r\n this.dispose();\r\n const co = opts.crossOrigin === undefined ? 'anonymous' : opts.crossOrigin;\r\n if (co === null) video.removeAttribute('crossorigin');\r\n else video.crossOrigin = co;\r\n video.playsInline = true;\r\n\r\n const { url, format } = source;\r\n const isHlsLike = format === 'hls' || format === 'dash';\r\n const nativeHls = video.canPlayType('application/vnd.apple.mpegurl') !== '';\r\n\r\n return new Promise<void>((resolve, reject) => {\r\n const cleanup = () => {\r\n video.removeEventListener('loadedmetadata', onLoaded);\r\n video.removeEventListener('error', onError);\r\n };\r\n const onLoaded = () => { cleanup(); resolve(); };\r\n const onError = () => {\r\n cleanup();\r\n const code = video.error ? video.error.code : 'unknown';\r\n reject(new Error(`Video failed to load (media error ${code}). Is the source reachable and CORS-clean?`));\r\n };\r\n video.addEventListener('loadedmetadata', onLoaded);\r\n video.addEventListener('error', onError);\r\n\r\n if (isHlsLike && !nativeHls) {\r\n import('hls.js').then(({ default: HlsCtor }) => {\r\n if (!HlsCtor.isSupported()) {\r\n cleanup();\r\n reject(new Error('HLS/DASH stream needs hls.js, which is unsupported in this browser.'));\r\n return;\r\n }\r\n this.hls = new HlsCtor({ enableWorker: true });\r\n this.hls.on(HlsCtor.Events.ERROR, (_e, data) => {\r\n if (data.fatal) { cleanup(); this.dispose(); reject(new Error(`HLS fatal error: ${data.type} / ${data.details}`)); }\r\n });\r\n this.hls.loadSource(url);\r\n this.hls.attachMedia(video);\r\n }).catch(() => {\r\n cleanup();\r\n reject(new Error('This looks like an HLS/DASH stream but hls.js could not be loaded. Install \"hls.js\".'));\r\n });\r\n } else {\r\n video.src = url;\r\n video.load();\r\n }\r\n });\r\n }\r\n\r\n dispose() {\r\n if (this.hls) { this.hls.destroy(); this.hls = null; }\r\n }\r\n}\r\n"],"names":["detectFormat","rawUrl","pathname","lower","ENDPOINTS","buildProxyUrl","proxy","format","base","params","name","value","MODES","PROJECTIONS","isFlatMode","p","_a","detectProjection","url","s","tb","sbs","StereoScene","opts","THREE","cb","w","h","canvas","video","projection","swapEyes","fov","supersampling","VRButton","ss","mode","vw","vh","kind","g","geo","split","eye","uv","m","swap","cfg","gL","gR","mL","mR","v","deg","DEG","clampAngles","lon","lat","LookControls","camera","dom","e","dx","dy","fn","id","_b","phi","theta","VideoSource","source","co","isHlsLike","nativeHls","resolve","reject","cleanup","onLoaded","onError","code","HlsCtor","_e","data"],"mappings":";;AASO,SAASA,EAAaC,GAA8B;AACzD,MAAIC,IAAWD;AACf,MAAI;AAAE,IAAAC,IAAW,IAAI,IAAID,CAAM,EAAE;AAAA,EAAU,QAAQ;AAAA,EAAiC;AACpF,QAAME,IAAQD,EAAS,YAAA;AACvB,SAAIC,EAAM,SAAS,OAAO,IAAU,QAChCA,EAAM,SAAS,MAAM,IAAU,SAC5B;AACT;AAEA,MAAMC,IAA0C;AAAA,EAC9C,aAAa;AAAA,EACb,KAAK;AAAA,EACL,MAAM;AACR;AAMO,SAASC,EAAcJ,GAAgBK,GAA4D;AACxG,QAAMC,IAASP,EAAaC,CAAM;AAClC,MAAI,CAACK,KAAS,CAACA,EAAM,IAAK,QAAO,EAAE,KAAKL,GAAQ,QAAAM,EAAA;AAChD,QAAMC,IAAOF,EAAM,IAAI,QAAQ,QAAQ,EAAE,GACnCG,IAAS,IAAI,gBAAA;AACnB,EAAAA,EAAO,IAAI,KAAKR,CAAM,GAClBK,EAAM,eAAaG,EAAO,IAAI,gBAAgBH,EAAM,WAAW;AACnE,aAAW,CAACI,GAAMC,CAAK,KAAK,OAAO,QAAQL,EAAM,WAAW,CAAA,CAAE;AAC5D,IAAIK,KAAS,QAAQA,MAAU,QAAW,IAAI,KAAKD,CAAI,IAAIC,CAAK;AAElE,SAAO,EAAE,KAAK,GAAGH,CAAI,GAAGJ,EAAUG,CAAM,CAAC,IAAIE,EAAO,UAAU,IAAI,QAAAF,EAAA;AACpE;ACzBO,MAAMK,IAAwC;AAAA,EACnD,WAAiB,EAAE,MAAM,aAAa,OAAO,OAAQ,QAAQ,GAAA;AAAA,EAC7D,YAAiB,EAAE,MAAM,aAAa,OAAO,QAAQ,QAAQ,GAAA;AAAA,EAC7D,YAAiB,EAAE,MAAM,aAAa,OAAO,QAAQ,QAAQ,GAAA;AAAA,EAC7D,WAAiB,EAAE,MAAM,aAAa,OAAO,OAAQ,QAAQ,GAAA;AAAA,EAC7D,UAAiB,EAAE,MAAM,aAAa,OAAO,MAAQ,QAAQ,GAAA;AAAA,EAC7D,WAAiB,EAAE,MAAM,SAAa,OAAO,QAAQ,QAAQ,IAAO,MAAM,IAAM,QAAQ,OAAA;AAAA,EACxF,iBAAiB,EAAE,MAAM,SAAa,OAAO,OAAQ,QAAQ,IAAO,MAAM,IAAM,QAAQ,UAAA;AAAA,EACxF,iBAAiB,EAAE,MAAM,SAAa,OAAO,OAAQ,QAAQ,IAAO,MAAM,IAAM,QAAQ,OAAA;AAC1F,GAEaC,IAAsD;AAAA,EACjE,EAAE,OAAO,WAAW,OAAO,mBAAA;AAAA,EAC3B,EAAE,OAAO,YAAY,OAAO,YAAA;AAAA,EAC5B,EAAE,OAAO,YAAY,OAAO,YAAA;AAAA,EAC5B,EAAE,OAAO,WAAW,OAAO,WAAA;AAAA,EAC3B,EAAE,OAAO,UAAU,OAAO,kBAAA;AAAA,EAC1B,EAAE,OAAO,WAAW,OAAO,UAAA;AAAA,EAC3B,EAAE,OAAO,iBAAiB,OAAO,qBAAA;AAAA,EACjC,EAAE,OAAO,iBAAiB,OAAO,qBAAA;AACnC;AAEO,SAASC,EAAWC,GAAwB;;AACjD,SAAO,CAAC,GAACC,IAAAJ,EAAMG,CAAC,MAAP,QAAAC,EAAU;AACrB;AAGO,SAASC,EAAiBC,GAAgC;AAC/D,QAAMC,IAAI,OAAOD,CAAG,EAAE,YAAA,GAChBE,IAAK,sDAAsD,KAAKD,CAAC,GACjEE,IAAM,uBAAuB,KAAKF,CAAC;AACzC,SAAIA,EAAE,SAAS,KAAK,IACdC,IAAW,WACXC,IAAY,YACT,aAELF,EAAE,SAAS,KAAK,KAAKA,EAAE,SAAS,OAAO,IAClCA,EAAE,SAAS,MAAM,IAAI,aAAa,YAEvCE,IAAYF,EAAE,SAAS,MAAM,IAAI,kBAAkB,kBAChD;AACT;AC7CO,MAAMG,EAAY;AAAA,EAoBvB,YAAYC,GAGT;AArBH,SAAS,QAAQ,IAAIC,EAAM,MAAA,GAQ3B,KAAiB,SAAuB,CAAA,GACxC,KAAiB,WAA2B,CAAA,GAC5C,KAAiB,UAAU,MAAM;AAC/B,iBAAWC,KAAM,KAAK,SAAU,CAAAA,EAAA;AAChC,WAAK,SAAS,OAAO,KAAK,OAAO,KAAK,MAAM;AAAA,IAC9C,GAyGA,KAAA,SAAS,MAAM;AACb,YAAMC,IAAI,KAAK,EAAA,GAAKC,IAAI,KAAK,EAAA;AAC7B,WAAK,OAAO,SAASD,IAAIC,GACzB,KAAK,OAAO,uBAAA,GACZ,KAAK,SAAS,QAAQD,GAAGC,GAAG,EAAK;AAAA,IACnC;AArGE,UAAM,EAAE,QAAAC,GAAQ,OAAAC,GAAO,YAAAC,IAAa,WAAW,UAAAC,IAAW,IAAO,KAAAC,IAAM,IAAI,eAAAC,IAAgB,IAAA,IAAQV;AACnG,SAAK,SAASK,GACd,KAAK,QAAQC,GACb,KAAK,cAAcjB,EAAMkB,CAAU,IAAIA,IAAa,WACpD,KAAK,cAAcC,GAEnB,KAAK,WAAW,IAAIP,EAAM,cAAc,EAAE,QAAAI,GAAQ,WAAW,IAAM,GACnE,KAAK,SAAS,cAAc,KAAK,cAAcK,CAAa,CAAC,GAC7D,KAAK,SAAS,QAAQ,KAAK,EAAA,GAAK,KAAK,EAAA,GAAK,EAAK,GAC/C,KAAK,SAAS,GAAG,UAAU,IAE3B,KAAK,SAAS,IAAIT,EAAM,kBAAkBQ,GAAK,KAAK,EAAA,IAAM,KAAK,KAAK,KAAK,GAAI,GAC7E,KAAK,OAAO,SAAS,IAAI,GAAG,GAAG,CAAC,GAChC,KAAK,OAAO,OAAO,OAAO,CAAC,GAE3B,KAAK,gBAAgB,KAAK,SAAS,aAAa,iBAAA,GAChD,KAAK,UAAU,IAAIR,EAAM,aAAaK,CAAK,GAC3C,KAAK,QAAQ,aAAaL,EAAM,gBAChC,KAAK,QAAQ,YAAYA,EAAM,cAC/B,KAAK,QAAQ,YAAYA,EAAM,cAC/B,KAAK,QAAQ,aAAa,KAAK,eAE/B,KAAK,gBAAgB,KAAK,aAAa,KAAK,WAAW,GACvDK,EAAM,iBAAiB,kBAAkB,MAAM;AAC7C,MAAIjB,EAAM,KAAK,WAAW,EAAE,aAAW,gBAAgB,KAAK,aAAa,KAAK,WAAW;AAAA,IAC3F,CAAC,GAED,KAAK,SAAS,iBAAiB,KAAK,OAAO,GAC3C,KAAK,WAAWsB,EAAS,aAAa,KAAK,QAAQ,GAEnD,KAAK,KAAK,IAAI,eAAe,MAAM,KAAK,QAAQ,GAChD,KAAK,GAAG,QAAQN,CAAM;AAAA,EACxB;AAAA,EAEQ,IAAI;AAAE,WAAO,KAAK,OAAO,eAAe;AAAA,EAAG;AAAA,EAC3C,IAAI;AAAE,WAAO,KAAK,OAAO,gBAAgB;AAAA,EAAG;AAAA,EAC5C,cAAcO,GAAY;AAAE,WAAO,KAAK,IAAI,OAAO,mBAAmBA,GAAI,CAAC;AAAA,EAAG;AAAA,EAE9E,YAAYC,GAAkB;AACpC,UAAMC,IAAK,KAAK,MAAM,YAAYC,IAAK,KAAK,MAAM;AAClD,WAAI,CAACD,KAAM,CAACC,IAAW,KAAK,IACrB1B,EAAMwB,CAAI,EAAE,WAAW,YAAaC,IAAK,IAAKC,IAAKD,IAAKC;AAAA,EACjE;AAAA,EAEQ,cAAcF,GAAwC;AAC5D,UAAMG,IAAO3B,EAAMwB,CAAI,EAAE;AACzB,QAAIG,MAAS,aAAa;AAAE,YAAMC,IAAI,IAAIhB,EAAM,eAAe,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,EAAE;AAAGgB,aAAAA,EAAE,MAAM,IAAI,GAAG,CAAC,GAAUA;AAAAA,IAAG;AACzI,QAAID,MAAS,aAAa;AAAE,YAAMC,IAAI,IAAIhB,EAAM,eAAe,KAAK,IAAI,EAAE;AAAGgB,aAAAA,EAAE,MAAM,IAAI,GAAG,CAAC,GAAUA;AAAAA,IAAG;AAC1G,UAAMb,IAAI,KAAKD,IAAIC,IAAI,KAAK,YAAYS,CAAI,GACtCI,IAAI,IAAIhB,EAAM,cAAcE,GAAGC,CAAC;AAAG,WAAAa,EAAE,UAAU,GAAG,GAAG,EAAE,GAAUA;AAAA,EACzE;AAAA,EAEQ,QAAQC,GAA2BC,GAAeC,GAAuB;AAC/E,QAAID,MAAU,OAAQ;AACtB,UAAME,IAAKH,EAAI,WAAW,GAAG;AAC7B,aAAS,IAAI,GAAG,IAAIG,EAAG,QAAQ,KAAK;AAClC,MAAIF,MAAU,QAAOE,EAAG,CAAC,IAAIA,EAAG,CAAC,IAAI,OAAOD,MAAQ,UAAU,MAAM,KAC3DD,MAAU,SAAME,EAAG,IAAI,CAAC,IAAIA,EAAG,IAAI,CAAC,IAAI,OAAOD,MAAQ,SAAS,MAAM;AAEjF,IAAAF,EAAI,WAAW,GAAG,cAAc;AAAA,EAClC;AAAA,EAEQ,cAAc;AACpB,eAAWI,KAAK,KAAK;AAAU,WAAK,MAAM,OAAOA,CAAC,GAAGA,EAAE,SAAS,QAAA,GAAYA,EAAE,SAA4B,QAAA;AAC1G,SAAK,OAAO,SAAS;AAAA,EACvB;AAAA,EAEQ,gBAAgBT,GAAkBU,GAAe;AACvD,IAAKlC,EAAMwB,CAAI,MAAGA,IAAO,YACzB,KAAK,YAAA;AACL,UAAMW,IAAMnC,EAAMwB,CAAI;AACtB,QAAKW,EAAI,QAIF;AACL,YAAMC,IAAK,KAAK,cAAcZ,CAAI;AAAG,WAAK,QAAQY,GAAID,EAAI,OAAO,MAAM;AACvE,YAAME,IAAK,KAAK,cAAcb,CAAI;AAAG,WAAK,QAAQa,GAAIF,EAAI,OAAO,OAAO;AACxE,YAAMG,IAAK,IAAI1B,EAAM,KAAKwB,GAAI,IAAIxB,EAAM,kBAAkB,EAAE,KAAK,KAAK,QAAA,CAAS,CAAC,GAC1E2B,IAAK,IAAI3B,EAAM,KAAKyB,GAAI,IAAIzB,EAAM,kBAAkB,EAAE,KAAK,KAAK,QAAA,CAAS,CAAC;AAChF,MAAA0B,EAAG,OAAO,IAAIJ,IAAO,IAAI,CAAC,GAAGK,EAAG,OAAO,IAAIL,IAAO,IAAI,CAAC,GACvD,KAAK,MAAM,IAAII,GAAIC,CAAE,GAAG,KAAK,OAAO,KAAKD,GAAIC,CAAE;AAAA,IACjD,OAXiB;AACf,YAAMN,IAAI,IAAIrB,EAAM,KAAK,KAAK,cAAcY,CAAI,GAAG,IAAIZ,EAAM,kBAAkB,EAAE,KAAK,KAAK,QAAA,CAAS,CAAC;AACrG,MAAAqB,EAAE,OAAO,IAAI,CAAC,GACd,KAAK,MAAM,IAAIA,CAAC,GAAG,KAAK,OAAO,KAAKA,CAAC;AAAA,IACvC;AAQA,SAAK,cAAcT,GAAM,KAAK,cAAcU;AAAA,EAC9C;AAAA,EAEA,cAAc/B,GAAe;AAAE,SAAK,gBAAgBA,GAAG,KAAK,WAAW;AAAA,EAAG;AAAA,EAC1E,YAAYqC,GAAY;AAAE,SAAK,gBAAgB,KAAK,aAAaA,CAAC;AAAA,EAAG;AAAA,EACrE,OAAOC,GAAa;AAAE,SAAK,OAAO,MAAMA,GAAK,KAAK,OAAO,uBAAA;AAAA,EAA0B;AAAA,EACnF,iBAAiBlB,GAAY;AAAE,SAAK,SAAS,cAAc,KAAK,cAAcA,CAAE,CAAC,GAAG,KAAK,SAAS,QAAQ,KAAK,EAAA,GAAK,KAAK,EAAA,GAAK,EAAK;AAAA,EAAG;AAAA,EACtI,gBAAgB;AAAE,WAAO,KAAK;AAAA,EAAa;AAAA,EAC3C,SAAS;AAAE,WAAO,CAAC,CAACvB,EAAM,KAAK,WAAW,EAAE;AAAA,EAAM;AAAA,EAClD,QAAQa,GAAgB;AAAE,SAAK,SAAS,KAAKA,CAAE;AAAA,EAAG;AAAA,EAClD,iBAAiB;AAAE,SAAK,SAAS,iBAAiB,IAAI;AAAA,EAAG;AAAA,EACzD,kBAAkB;AAAE,SAAK,SAAS,iBAAiB,KAAK,OAAO;AAAA,EAAG;AAAA,EASlE,UAAU;AACR,SAAK,GAAG,WAAA,GACR,KAAK,SAAS,iBAAiB,IAAI,GACnC,KAAK,QAAQ,QAAA,GACb,KAAK,YAAA,GACL,KAAK,SAAS,QAAA;AAAA,EAChB;AACF;AC9IA,MAAM6B,IAAM,KAAK,KAAK;AAGf,SAASC,EAAYC,GAAaC,GAA2C;AAClF,SAAO;AAAA,IACL,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,IAAID,CAAG,CAAC;AAAA,IACpC,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,IAAIC,CAAG,CAAC;AAAA,EAAA;AAExC;AAMO,MAAMC,EAAa;AAAA,EASxB,YACmBC,GACAC,GACjBrC,IAAyC,CAAA,GACzC;AAHiB,SAAA,SAAAoC,GACA,KAAA,MAAAC,GAVnB,KAAQ,MAAM,GACd,KAAQ,MAAM,GACd,KAAQ,WAAW,IACnB,KAAQ,KAAK,GACb,KAAQ,KAAK,GACb,KAAQ,UAAU,IAmBlB,KAAQ,SAAS,CAACC,MAAoB;AACpC,MAAK,KAAK,YACV,KAAK,WAAW,IAChB,KAAK,KAAKA,EAAE,SACZ,KAAK,KAAKA,EAAE,SACZ,KAAK,QAAQ,qBAAqBA,EAAE,SAAS;AAAA,IAC/C,GAEA,KAAQ,SAAS,CAACA,MAAoB;AACpC,UAAI,CAAC,KAAK,SAAU;AACpB,YAAMC,IAAKD,EAAE,UAAU,KAAK,IACtBE,IAAKF,EAAE,UAAU,KAAK;AAC5B,WAAK,KAAKA,EAAE,SACZ,KAAK,KAAKA,EAAE,SACX,EAAE,KAAK,KAAK,KAAK,KAAK,KAAK,QAAQN,EAAY,KAAK,MAAMO,IAAK,MAAM,KAAK,MAAMC,IAAK,IAAI;AAAA,IAC5F,GAEA,KAAQ,OAAO,CAACF,MAAoB;AAClC,WAAK,WAAW,IAChB,KAAK,QAAQ,yBAAyBA,EAAE,SAAS;AAAA,IACnD,GA/BE,KAAK,eAAetC,EAAK,iBAAiB,MAAM,KAChD,KAAK,IAAI,iBAAiB,eAAe,KAAK,MAAM,GACpD,KAAK,IAAI,iBAAiB,eAAe,KAAK,MAAM,GACpD,KAAK,IAAI,iBAAiB,aAAa,KAAK,IAAI,GAChD,KAAK,IAAI,iBAAiB,iBAAiB,KAAK,IAAI;AAAA,EACtD;AAAA,EAEQ,QAAQyC,GAAmDC,GAAY;;AAC7E,QAAI;AAAE,OAAAC,KAAAlD,IAAA,KAAK,KAAIgD,OAAT,QAAAE,EAAA,KAAAlD,GAAeiD;AAAA,IAAK,QAAQ;AAAA,IAA2B;AAAA,EAC/D;AAAA,EAwBA,SAAS;AACP,QAAI,KAAK,aAAA,KAAkB,CAAC,KAAK,QAAS;AAC1C,UAAME,KAAO,KAAK,KAAK,OAAOb,GACxBc,IAAQ,KAAK,MAAMd;AACzB,SAAK,OAAO;AAAA,MACV,KAAK,IAAIa,CAAG,IAAI,KAAK,IAAIC,CAAK;AAAA,MAC9B,KAAK,IAAID,CAAG;AAAA,MACZ,CAAC,KAAK,IAAIA,CAAG,IAAI,KAAK,IAAIC,CAAK;AAAA,IAAA;AAAA,EAEnC;AAAA,EAEA,QAAQ;AAAE,SAAK,MAAM,GAAG,KAAK,MAAM;AAAA,EAAG;AAAA,EAEtC,WAAWhB,GAAY;AACrB,SAAK,UAAUA,GACVA,MAAK,KAAK,MAAM,GAAG,KAAK,MAAM,GAAG,KAAK,OAAO,OAAO,GAAG,GAAG,EAAE;AAAA,EACnE;AAAA,EAEA,YAAY;AAAE,WAAO,EAAE,KAAK,KAAK,KAAK,KAAK,KAAK,IAAA;AAAA,EAAO;AAAA,EAEvD,UAAU;AACR,SAAK,IAAI,oBAAoB,eAAe,KAAK,MAAM,GACvD,KAAK,IAAI,oBAAoB,eAAe,KAAK,MAAM,GACvD,KAAK,IAAI,oBAAoB,aAAa,KAAK,IAAI,GACnD,KAAK,IAAI,oBAAoB,iBAAiB,KAAK,IAAI;AAAA,EACzD;AACF;ACjFO,MAAMiB,EAAY;AAAA,EAAlB,cAAA;AACL,SAAQ,MAAkB;AAAA,EAAA;AAAA,EAE1B,MAAM,OACJxC,GACAyC,GACA/C,IAAwC,CAAA,GACzB;AACf,SAAK,QAAA;AACL,UAAMgD,IAAKhD,EAAK,gBAAgB,SAAY,cAAcA,EAAK;AAC/D,IAAIgD,MAAO,OAAM1C,EAAM,gBAAgB,aAAa,MACzC,cAAc0C,GACzB1C,EAAM,cAAc;AAEpB,UAAM,EAAE,KAAAX,GAAK,QAAAX,EAAA,IAAW+D,GAClBE,IAAYjE,MAAW,SAASA,MAAW,QAC3CkE,IAAY5C,EAAM,YAAY,+BAA+B,MAAM;AAEzE,WAAO,IAAI,QAAc,CAAC6C,GAASC,MAAW;AAC5C,YAAMC,IAAU,MAAM;AACpB,QAAA/C,EAAM,oBAAoB,kBAAkBgD,CAAQ,GACpDhD,EAAM,oBAAoB,SAASiD,CAAO;AAAA,MAC5C,GACMD,IAAW,MAAM;AAAE,QAAAD,EAAA,GAAWF,EAAA;AAAA,MAAW,GACzCI,IAAU,MAAM;AACpB,QAAAF,EAAA;AACA,cAAMG,IAAOlD,EAAM,QAAQA,EAAM,MAAM,OAAO;AAC9C,QAAA8C,EAAO,IAAI,MAAM,qCAAqCI,CAAI,4CAA4C,CAAC;AAAA,MACzG;AACA,MAAAlD,EAAM,iBAAiB,kBAAkBgD,CAAQ,GACjDhD,EAAM,iBAAiB,SAASiD,CAAO,GAEnCN,KAAa,CAACC,IAChB,OAAO,QAAQ,EAAE,KAAK,CAAC,EAAE,SAASO,QAAc;AAC9C,YAAI,CAACA,EAAQ,eAAe;AAC1B,UAAAJ,EAAA,GACAD,EAAO,IAAI,MAAM,qEAAqE,CAAC;AACvF;AAAA,QACF;AACA,aAAK,MAAM,IAAIK,EAAQ,EAAE,cAAc,IAAM,GAC7C,KAAK,IAAI,GAAGA,EAAQ,OAAO,OAAO,CAACC,GAAIC,MAAS;AAC9C,UAAIA,EAAK,UAASN,EAAA,GAAW,KAAK,QAAA,GAAWD,EAAO,IAAI,MAAM,oBAAoBO,EAAK,IAAI,MAAMA,EAAK,OAAO,EAAE,CAAC;AAAA,QAClH,CAAC,GACD,KAAK,IAAI,WAAWhE,CAAG,GACvB,KAAK,IAAI,YAAYW,CAAK;AAAA,MAC5B,CAAC,EAAE,MAAM,MAAM;AACb,QAAA+C,EAAA,GACAD,EAAO,IAAI,MAAM,sFAAsF,CAAC;AAAA,MAC1G,CAAC,KAED9C,EAAM,MAAMX,GACZW,EAAM,KAAA;AAAA,IAEV,CAAC;AAAA,EACH;AAAA,EAEA,UAAU;AACR,IAAI,KAAK,QAAO,KAAK,IAAI,QAAA,GAAW,KAAK,MAAM;AAAA,EACjD;AACF;"}
|
package/dist/core.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as o, M as s, P as t, S as r, V as c, b as d, c as l, d as S, a as i, i as n } from "./VideoSource-
|
|
1
|
+
import { L as o, M as s, P as t, S as r, V as c, b as d, c as l, d as S, a as i, i as n } from "./VideoSource-BGaVaGUn.js";
|
|
2
2
|
export {
|
|
3
3
|
o as LookControls,
|
|
4
4
|
s as MODES,
|
package/dist/three-vr-player.js
CHANGED
|
@@ -1,92 +1,111 @@
|
|
|
1
|
-
import { P as
|
|
2
|
-
import { M as
|
|
3
|
-
function
|
|
1
|
+
import { P as Y, V as _, S as H, L as K, a as Q, b as X } from "./VideoSource-BGaVaGUn.js";
|
|
2
|
+
import { M as rt, c as at, d as pt, i as lt } from "./VideoSource-BGaVaGUn.js";
|
|
3
|
+
function $(l) {
|
|
4
4
|
if (!Number.isFinite(l) || l < 0) return "0:00";
|
|
5
|
-
const t = Math.floor(l % 60),
|
|
6
|
-
return
|
|
5
|
+
const t = Math.floor(l % 60), e = Math.floor(l / 60 % 60), s = Math.floor(l / 3600), p = String(t).padStart(2, "0");
|
|
6
|
+
return s > 0 ? `${s}:${String(e).padStart(2, "0")}:${p}` : `${e}:${p}`;
|
|
7
7
|
}
|
|
8
|
-
function o(l, t = {},
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
for (const
|
|
12
|
-
return
|
|
8
|
+
function o(l, t = {}, e = []) {
|
|
9
|
+
const s = document.createElement(l), { class: p, ...c } = t;
|
|
10
|
+
p && (s.className = p), Object.assign(s, c);
|
|
11
|
+
for (const u of e) s.append(u);
|
|
12
|
+
return s;
|
|
13
13
|
}
|
|
14
|
-
class
|
|
15
|
-
constructor(t,
|
|
14
|
+
class Z {
|
|
15
|
+
constructor(t, e) {
|
|
16
16
|
this.nodes = [], this.disposers = [];
|
|
17
|
-
const
|
|
18
|
-
for (const i of
|
|
19
|
-
const
|
|
20
|
-
|
|
17
|
+
const s = e.video, p = o("button", { class: "tvp-btn tvp-play", title: "Play/Pause", textContent: "▶" }), c = o("input", { class: "tvp-seek", type: "range", min: "0", max: "1000", value: "0" }), u = o("span", { class: "tvp-time", textContent: "0:00 / 0:00" }), r = o("button", { class: "tvp-btn tvp-mute", title: "Volume", textContent: "🔊" }), v = o("input", { class: "tvp-volume", type: "range", min: "0", max: "1", step: "0.01", value: "1" }), f = o("div", { class: "tvp-volpopup", hidden: !0 }, [v]), G = o("span", { class: "tvp-volwrap" }, [r, f]), z = o("span", { class: "tvp-vrslot" }), b = o("button", { class: "tvp-btn tvp-projbtn", title: "Projection", textContent: "🌐" }), d = o("div", { class: "tvp-projmenu", hidden: !0 });
|
|
18
|
+
for (const i of Y) {
|
|
19
|
+
const n = o("button", { textContent: i.label });
|
|
20
|
+
n.dataset.mode = i.value, d.append(n);
|
|
21
21
|
}
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
o("label", {
|
|
22
|
+
const M = o("button", { textContent: "Off (native player)" });
|
|
23
|
+
M.dataset.mode = "off", d.append(o("hr", { class: "tvp-sep" }), M);
|
|
24
|
+
const J = o("span", { class: "tvp-projwrap" }, [b, d]), k = o("button", { class: "tvp-btn tvp-settingsbtn", title: "Settings", textContent: "⚙" }), O = o("button", { class: "tvp-btn tvp-fullscreen", title: "Fullscreen", textContent: "⛶" }), S = o("footer", { class: "tvp-controls" }, [p, c, u, G, z, J, k, O]), P = o("input", { type: "checkbox", checked: e.initial.swapEyes }), x = o("input", { type: "range", min: "30", max: "100", step: "1", value: String(e.initial.fov) }), j = o("span", { textContent: String(e.initial.fov) }), E = o("input", { type: "range", min: "1", max: "2", step: "0.25", value: String(e.initial.supersampling) }), A = o("span", { textContent: String(e.initial.supersampling) }), C = o("input", { type: "checkbox", checked: e.proxy.enabled }), F = o("input", { type: "text", value: e.proxy.url, placeholder: "http://localhost:8888", spellcheck: !1 }), N = o("input", { type: "password", value: e.proxy.apiPassword, placeholder: "API password" }), g = o("section", { class: "tvp-settings" }, [
|
|
25
|
+
o("label", { class: "row" }, [P, "Swap eyes (if depth looks wrong)"]),
|
|
26
|
+
o("label", {}, [D("Field of view (zoom): ", j, "°"), x]),
|
|
27
|
+
o("label", {}, [D("Supersampling: ", A, "× (sharpness)"), E]),
|
|
26
28
|
o("hr", { class: "tvp-sep" }),
|
|
27
|
-
o("label", { class: "row" }, [
|
|
28
|
-
o("label", {}, ["Proxy URL",
|
|
29
|
-
o("label", {}, ["API password",
|
|
30
|
-
]),
|
|
31
|
-
this.nodes.push(
|
|
29
|
+
o("label", { class: "row" }, [C, "Use CORS proxy"]),
|
|
30
|
+
o("label", {}, ["Proxy URL", F]),
|
|
31
|
+
o("label", {}, ["API password", N])
|
|
32
|
+
]), W = o("div", { class: "tvp-toast" });
|
|
33
|
+
this.nodes.push(S, g, W);
|
|
32
34
|
for (const i of this.nodes) t.append(i);
|
|
33
|
-
const
|
|
34
|
-
i.addEventListener(
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}),
|
|
41
|
-
|
|
42
|
-
}),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
const a = (i, n, h, m) => {
|
|
36
|
+
i.addEventListener(n, h, m), this.disposers.push(() => i.removeEventListener(n, h, m));
|
|
37
|
+
}, I = (i) => c.style.setProperty("--seek", `${i}%`), y = () => {
|
|
38
|
+
f.hidden = !0, d.hidden = !0, g.classList.remove("open");
|
|
39
|
+
};
|
|
40
|
+
a(p, "click", () => {
|
|
41
|
+
s.paused ? s.play() : s.pause();
|
|
42
|
+
}), a(s, "play", () => {
|
|
43
|
+
p.textContent = "⏸";
|
|
44
|
+
}), a(s, "pause", () => {
|
|
45
|
+
p.textContent = "▶";
|
|
46
|
+
}), a(s, "timeupdate", () => {
|
|
47
|
+
if (s.duration) {
|
|
48
|
+
const i = s.currentTime / s.duration * 100;
|
|
49
|
+
c.value = String(i * 10), I(i), u.textContent = `${$(s.currentTime)} / ${$(s.duration)}`;
|
|
46
50
|
}
|
|
47
|
-
}),
|
|
48
|
-
|
|
49
|
-
}),
|
|
50
|
-
i.stopPropagation()
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
}), a(c, "input", () => {
|
|
52
|
+
I(Number(c.value) / 10), s.duration && (s.currentTime = Number(c.value) / 1e3 * s.duration);
|
|
53
|
+
}), a(r, "click", (i) => {
|
|
54
|
+
i.stopPropagation();
|
|
55
|
+
const n = f.hidden;
|
|
56
|
+
y(), f.hidden = !n;
|
|
57
|
+
}), a(v, "input", () => {
|
|
58
|
+
s.volume = Number(v.value), s.muted = s.volume === 0, r.textContent = s.muted ? "🔇" : "🔊";
|
|
53
59
|
});
|
|
54
|
-
const
|
|
55
|
-
const i =
|
|
56
|
-
let
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
}),
|
|
60
|
+
const B = () => {
|
|
61
|
+
const i = e.getProjection();
|
|
62
|
+
let n = "Projection";
|
|
63
|
+
d.querySelectorAll("button").forEach((h) => {
|
|
64
|
+
const m = h.dataset.mode === i;
|
|
65
|
+
h.classList.toggle("active", m), m && (n = `Projection: ${h.textContent}`);
|
|
66
|
+
}), b.title = n;
|
|
61
67
|
};
|
|
62
|
-
|
|
63
|
-
i.stopPropagation()
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}),
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
a(b, "click", (i) => {
|
|
69
|
+
i.stopPropagation();
|
|
70
|
+
const n = d.hidden;
|
|
71
|
+
y(), d.hidden = !n;
|
|
72
|
+
}), a(d, "click", (i) => {
|
|
73
|
+
const n = i.target.closest("button[data-mode]");
|
|
74
|
+
n && (e.setProjection(n.dataset.mode), B(), d.hidden = !0);
|
|
75
|
+
}), B(), a(k, "click", (i) => {
|
|
76
|
+
i.stopPropagation();
|
|
77
|
+
const n = !g.classList.contains("open");
|
|
78
|
+
y(), g.classList.toggle("open", n);
|
|
79
|
+
}), a(P, "change", () => e.setSwapEyes(P.checked)), a(x, "input", () => {
|
|
80
|
+
const i = Number(x.value);
|
|
81
|
+
j.textContent = String(i), e.setFov(i);
|
|
82
|
+
}), a(E, "input", () => {
|
|
83
|
+
const i = Number(E.value);
|
|
84
|
+
A.textContent = String(i), e.setSupersampling(i);
|
|
75
85
|
});
|
|
76
|
-
const
|
|
77
|
-
|
|
86
|
+
const T = () => e.setProxy({ url: F.value.trim(), apiPassword: N.value, enabled: C.checked });
|
|
87
|
+
a(C, "change", T), a(F, "change", T), a(N, "change", T), a(e.surface, "wheel", (i) => {
|
|
78
88
|
i.preventDefault();
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
}, { passive: !1 }),
|
|
82
|
-
var
|
|
83
|
-
const i =
|
|
84
|
-
document.fullscreenElement ? (
|
|
85
|
-
}),
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
})
|
|
89
|
-
|
|
89
|
+
const n = Math.max(30, Math.min(100, Number(x.value) + Math.sign(i.deltaY) * 3));
|
|
90
|
+
x.value = String(n), j.textContent = String(n), e.setFov(n);
|
|
91
|
+
}, { passive: !1 }), a(O, "click", () => {
|
|
92
|
+
var n, h;
|
|
93
|
+
const i = e.fullscreenTarget;
|
|
94
|
+
document.fullscreenElement ? (h = document.exitFullscreen) == null || h.call(document) : (n = i.requestFullscreen) == null || n.call(i);
|
|
95
|
+
}), a(document, "click", (i) => {
|
|
96
|
+
const n = i.composedPath(), h = (m) => n.includes(m);
|
|
97
|
+
[f, r, d, b, g, k].some(h) || y();
|
|
98
|
+
});
|
|
99
|
+
let w = 0;
|
|
100
|
+
const q = () => !f.hidden || !d.hidden || g.classList.contains("open"), R = () => {
|
|
101
|
+
q() || S.classList.add("tvp-hidden");
|
|
102
|
+
}, L = () => {
|
|
103
|
+
S.classList.remove("tvp-hidden"), clearTimeout(w), w = window.setTimeout(R, 5e3);
|
|
104
|
+
};
|
|
105
|
+
a(e.fullscreenTarget, "pointermove", L), a(e.fullscreenTarget, "pointerdown", L), a(e.fullscreenTarget, "pointerleave", () => {
|
|
106
|
+
clearTimeout(w), R();
|
|
107
|
+
}), this.disposers.push(() => clearTimeout(w)), L(), e.vrSupported().then((i) => {
|
|
108
|
+
i && (Object.assign(e.vrButton.style, { position: "static", left: "auto", bottom: "auto", transform: "none", margin: "0" }), z.append(e.vrButton));
|
|
90
109
|
});
|
|
91
110
|
}
|
|
92
111
|
dispose() {
|
|
@@ -94,82 +113,82 @@ class _ {
|
|
|
94
113
|
for (const t of this.nodes) t.remove();
|
|
95
114
|
}
|
|
96
115
|
}
|
|
97
|
-
function
|
|
98
|
-
const
|
|
99
|
-
return
|
|
116
|
+
function D(l, t, e) {
|
|
117
|
+
const s = document.createDocumentFragment();
|
|
118
|
+
return s.append(l, t, e), s;
|
|
100
119
|
}
|
|
101
|
-
const
|
|
102
|
-
class
|
|
103
|
-
constructor(t,
|
|
104
|
-
var c,
|
|
105
|
-
this.source = new
|
|
106
|
-
const
|
|
120
|
+
const U = ":host,:host *,.tvp,.tvp *{box-sizing:border-box}.tvp-canvas{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;display:block;touch-action:none;cursor:grab}.tvp-canvas:active{cursor:grabbing}.tvp-video{display:none}.tvp-controls{position:absolute;left:0;right:0;bottom:0;display:flex;align-items:center;gap:10px;padding:12px;background:linear-gradient(transparent,#000c);z-index:5;font:14px system-ui,Segoe UI,Roboto,sans-serif;color:#e8eaed;transition:opacity .3s}.tvp-controls.tvp-hidden{opacity:0;pointer-events:none}.tvp-btn{padding:4px;border:0;background:none;color:#e8eaed;cursor:pointer;font-size:22px;line-height:1}.tvp-btn:hover{opacity:.7}.tvp-seek{flex:1;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:14px;background:transparent;cursor:pointer;margin:0}.tvp-seek::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:linear-gradient(to right,#4f8cff var(--seek,0%),#3a4150 var(--seek,0%))}.tvp-seek::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-top:-4px;width:12px;height:12px;border-radius:50%;background:#fff;cursor:pointer}.tvp-seek::-moz-range-track{height:4px;border-radius:2px;background:#3a4150}.tvp-seek::-moz-range-progress{height:4px;border-radius:2px;background:#4f8cff}.tvp-seek::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:#fff;cursor:pointer}.tvp-time{font-variant-numeric:tabular-nums;min-width:96px;text-align:center;color:#cfd6e2}.tvp-volwrap,.tvp-projwrap{position:relative;display:inline-flex}.tvp-volpopup{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);width:40px;height:132px;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:10px;z-index:8;box-shadow:0 8px 24px #0009}.tvp-volpopup[hidden]{display:none}.tvp-volume{position:absolute;top:50%;left:50%;width:104px;height:14px;margin:0;transform:translate(-50%,-50%) rotate(-90deg);-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;cursor:pointer}.tvp-volume::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:#3a4150}.tvp-volume::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-top:-4px;width:12px;height:12px;border-radius:50%;background:#fff;cursor:pointer}.tvp-volume::-moz-range-track{height:4px;border-radius:2px;background:#3a4150}.tvp-volume::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:#fff;cursor:pointer}.tvp-projmenu{position:absolute;bottom:calc(100% + 8px);right:0;min-width:210px;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:10px;padding:6px;display:flex;flex-direction:column;gap:2px;z-index:8;box-shadow:0 8px 24px #0009}.tvp-projmenu[hidden]{display:none}.tvp-projmenu button{text-align:left;background:transparent;border:0;color:#e8eaed;padding:8px 10px;border-radius:7px;cursor:pointer;font:inherit;white-space:nowrap}.tvp-projmenu button:hover{background:#252b39}.tvp-projmenu button.active{background:#4f8cff;color:#fff}.tvp-vrslot button{position:static!important}.tvp-settings{position:absolute;bottom:62px;right:10px;width:300px;max-width:calc(100% - 20px);max-height:70%;overflow-y:auto;background:#121418eb;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid #2a2f3a;border-radius:12px;padding:14px;display:none;flex-direction:column;gap:12px;z-index:6;font:14px system-ui,Segoe UI,Roboto,sans-serif;color:#e8eaed}.tvp-settings.open{display:flex}.tvp-settings label{display:flex;flex-direction:column;gap:4px;font-size:12px;color:#aab2c0}.tvp-settings label.row{flex-direction:row;align-items:center;gap:8px;color:#e8eaed;font-size:13px}.tvp-settings input[type=range]{width:100%;accent-color:#4f8cff}.tvp-settings input[type=text],.tvp-settings input[type=password]{width:100%;padding:7px 9px;border-radius:7px;border:1px solid #333;background:#151821;color:#e8eaed;font:inherit}.tvp-sep{width:100%;border:0;border-top:1px solid #2a2f3a;margin:2px 0}.tvp-toast{position:absolute;left:50%;bottom:74px;transform:translate(-50%);max-width:80%;padding:10px 16px;border-radius:10px;background:#1b1f2aed;border:1px solid #2a2f3a;color:#e8eaed;opacity:0;pointer-events:none;transition:opacity .2s;z-index:7;font:13px system-ui}.tvp-toast.show{opacity:1}", V = "three-vr-player:settings";
|
|
121
|
+
class tt {
|
|
122
|
+
constructor(t, e = {}) {
|
|
123
|
+
var c, u;
|
|
124
|
+
this.source = new _(), this.listeners = /* @__PURE__ */ new Map(), this.readyEmitted = !1, this.native = !1, this.tainted = !1, this.loading = !1, this.useProxy = !1, this.opts = e, this.proxyConfig = e.proxy, this.useProxy = !!e.proxy;
|
|
125
|
+
const s = e.persistSettings ? this.loadSettings() : null;
|
|
107
126
|
this.view = {
|
|
108
|
-
projection:
|
|
109
|
-
swapEyes:
|
|
110
|
-
fov:
|
|
111
|
-
supersampling:
|
|
112
|
-
}, this.wrap = document.createElement("div"), this.wrap.className = "tvp", this.wrap.style.cssText = "position:relative;width:100%;height:100%;overflow:hidden;", t.appendChild(this.wrap);
|
|
113
|
-
let
|
|
114
|
-
if (
|
|
115
|
-
const
|
|
116
|
-
|
|
127
|
+
projection: e.projection ?? (s == null ? void 0 : s.projection) ?? "180-sbs",
|
|
128
|
+
swapEyes: e.swapEyes ?? (s == null ? void 0 : s.swapEyes) ?? !1,
|
|
129
|
+
fov: e.fov ?? (s == null ? void 0 : s.fov) ?? 70,
|
|
130
|
+
supersampling: e.supersampling ?? (s == null ? void 0 : s.supersampling) ?? 1.5
|
|
131
|
+
}, this.displayMode = this.view.projection, this.wrap = document.createElement("div"), this.wrap.className = "tvp", this.wrap.style.cssText = "position:relative;width:100%;height:100%;overflow:hidden;", t.appendChild(this.wrap);
|
|
132
|
+
let p;
|
|
133
|
+
if (e.shadowDom !== !1) {
|
|
134
|
+
const r = this.wrap.attachShadow({ mode: "open" }), v = document.createElement("style");
|
|
135
|
+
v.textContent = U, r.appendChild(v), p = r;
|
|
117
136
|
} else {
|
|
118
137
|
if (!document.getElementById("tvp-styles")) {
|
|
119
|
-
const
|
|
120
|
-
|
|
138
|
+
const r = document.createElement("style");
|
|
139
|
+
r.id = "tvp-styles", r.textContent = U, document.head.appendChild(r);
|
|
121
140
|
}
|
|
122
|
-
|
|
141
|
+
p = this.wrap;
|
|
123
142
|
}
|
|
124
|
-
this.canvas = document.createElement("canvas"), this.canvas.className = "tvp-canvas", this.video = document.createElement("video"), this.video.className = "tvp-video", this.video.playsInline = !0,
|
|
143
|
+
this.canvas = document.createElement("canvas"), this.canvas.className = "tvp-canvas", this.video = document.createElement("video"), this.video.className = "tvp-video", this.video.playsInline = !0, e.crossOrigin !== null && (this.video.crossOrigin = e.crossOrigin ?? "anonymous"), p.append(this.canvas, this.video), this.scene = new H({
|
|
125
144
|
canvas: this.canvas,
|
|
126
145
|
video: this.video,
|
|
127
146
|
projection: this.view.projection,
|
|
128
147
|
swapEyes: this.view.swapEyes,
|
|
129
148
|
fov: this.view.fov,
|
|
130
149
|
supersampling: this.view.supersampling
|
|
131
|
-
}), this.look = new
|
|
150
|
+
}), this.look = new K(this.scene.camera, this.canvas, { isPresenting: () => this.scene.renderer.xr.isPresenting }), this.scene.onFrame(() => this.look.update()), this.look.setEnabled(!this.scene.isFlat()), e.controls !== !1 && (this.ui = new Z(p, {
|
|
132
151
|
video: this.video,
|
|
133
152
|
surface: this.canvas,
|
|
134
153
|
fullscreenTarget: this.wrap,
|
|
135
154
|
vrButton: this.scene.vrButton,
|
|
136
155
|
vrSupported: () => this.vrSupported(),
|
|
137
|
-
getProjection: () => this.
|
|
138
|
-
setProjection: (
|
|
139
|
-
setSwapEyes: (
|
|
140
|
-
setFov: (
|
|
141
|
-
setSupersampling: (
|
|
156
|
+
getProjection: () => this.displayMode,
|
|
157
|
+
setProjection: (r) => this.setProjection(r),
|
|
158
|
+
setSwapEyes: (r) => this.setSwapEyes(r),
|
|
159
|
+
setFov: (r) => this.setFov(r),
|
|
160
|
+
setSupersampling: (r) => this.setSupersampling(r),
|
|
142
161
|
initial: { swapEyes: this.view.swapEyes, fov: this.view.fov, supersampling: this.view.supersampling },
|
|
143
|
-
proxy: { url: ((c = this.proxyConfig) == null ? void 0 : c.url) ?? "", apiPassword: ((
|
|
144
|
-
setProxy: (
|
|
162
|
+
proxy: { url: ((c = this.proxyConfig) == null ? void 0 : c.url) ?? "", apiPassword: ((u = this.proxyConfig) == null ? void 0 : u.apiPassword) ?? "", enabled: this.useProxy },
|
|
163
|
+
setProxy: (r) => this.setProxy(r)
|
|
145
164
|
})), this.video.addEventListener("play", () => this.emit("play")), this.video.addEventListener("pause", () => this.emit("pause")), this.video.addEventListener("ended", () => this.emit("ended")), this.video.addEventListener("timeupdate", () => this.emit("timeupdate", this.video.currentTime)), this.video.addEventListener("error", () => {
|
|
146
165
|
this.loading || this.emit("error", this.video.error);
|
|
147
166
|
}), this.video.addEventListener("loadedmetadata", () => {
|
|
148
167
|
this.readyEmitted || (this.readyEmitted = !0, this.emit("ready"));
|
|
149
|
-
}), this.scene.renderer.xr.addEventListener("sessionstart", () => this.emit("enterxr")), this.scene.renderer.xr.addEventListener("sessionend", () => this.emit("exitxr")),
|
|
168
|
+
}), this.scene.renderer.xr.addEventListener("sessionstart", () => this.emit("enterxr")), this.scene.renderer.xr.addEventListener("sessionend", () => this.emit("exitxr")), e.src && this.load(e.src, { projection: e.projection });
|
|
150
169
|
}
|
|
151
170
|
vrSupported() {
|
|
152
171
|
return this.opts.vrButton === !1 || !navigator.xr ? Promise.resolve(!1) : navigator.xr.isSessionSupported("immersive-vr").catch(() => !1);
|
|
153
172
|
}
|
|
154
|
-
async load(t,
|
|
173
|
+
async load(t, e = {}) {
|
|
155
174
|
this.currentSrc = t;
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
const { url:
|
|
175
|
+
const s = e.projection ?? (this.opts.autoDetect !== !1 ? Q(t) : null);
|
|
176
|
+
s && this.applyProjectionGeometry(s), this.displayMode !== "off" && (this.displayMode = this.view.projection);
|
|
177
|
+
const { url: p, format: c } = X(t, this.useProxy ? this.proxyConfig : void 0), u = this.opts.crossOrigin === void 0 ? "anonymous" : this.opts.crossOrigin;
|
|
159
178
|
this.loading = !0;
|
|
160
179
|
try {
|
|
161
|
-
await this.source.attach(this.video, { url:
|
|
180
|
+
await this.source.attach(this.video, { url: p, format: c }, { crossOrigin: u }), this.tainted = !1, this.applyDisplay(), await this.video.play().catch(() => {
|
|
162
181
|
});
|
|
163
|
-
} catch (
|
|
164
|
-
if (this.opts.nativeFallback !== !1 && c === "progressive" &&
|
|
182
|
+
} catch (r) {
|
|
183
|
+
if (this.opts.nativeFallback !== !1 && c === "progressive" && u !== null)
|
|
165
184
|
try {
|
|
166
|
-
this.setNativeFallback(!0), await this.source.attach(this.video, { url:
|
|
185
|
+
this.tainted = !0, this.setNativeFallback(!0), await this.source.attach(this.video, { url: p, format: c }, { crossOrigin: null }), await this.video.play().catch(() => {
|
|
167
186
|
}), this.emit("fallback");
|
|
168
187
|
return;
|
|
169
|
-
} catch (
|
|
170
|
-
throw this.setNativeFallback(!1), this.emit("error",
|
|
188
|
+
} catch (v) {
|
|
189
|
+
throw this.tainted = !1, this.setNativeFallback(!1), this.emit("error", v), v;
|
|
171
190
|
}
|
|
172
|
-
throw this.setNativeFallback(!1), this.emit("error",
|
|
191
|
+
throw this.setNativeFallback(!1), this.emit("error", r), r;
|
|
173
192
|
} finally {
|
|
174
193
|
this.loading = !1;
|
|
175
194
|
}
|
|
@@ -193,8 +212,19 @@ class H {
|
|
|
193
212
|
pause() {
|
|
194
213
|
this.video.pause();
|
|
195
214
|
}
|
|
215
|
+
/** Set the display mode: a geometry projection (WebGL 3D) or 'off' for plain 2D `<video>`. */
|
|
196
216
|
setProjection(t) {
|
|
197
|
-
|
|
217
|
+
if (t === "off") {
|
|
218
|
+
this.displayMode = "off", this.setNativeFallback(!0), this.emit("projectionchange", t);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
this.displayMode = t, this.applyProjectionGeometry(t), this.tainted && this.currentSrc ? this.load(this.currentSrc) : this.setNativeFallback(!1), this.emit("projectionchange", t);
|
|
222
|
+
}
|
|
223
|
+
applyProjectionGeometry(t) {
|
|
224
|
+
this.scene.setProjection(t), this.look.setEnabled(!this.scene.isFlat()), this.look.reset(), this.view.projection = t, this.persist();
|
|
225
|
+
}
|
|
226
|
+
applyDisplay() {
|
|
227
|
+
this.setNativeFallback(this.displayMode === "off");
|
|
198
228
|
}
|
|
199
229
|
setSwapEyes(t) {
|
|
200
230
|
this.scene.setSwapEyes(t), this.view.swapEyes = t, this.persist();
|
|
@@ -210,35 +240,35 @@ class H {
|
|
|
210
240
|
this.proxyConfig = t.url ? { url: t.url, apiPassword: t.apiPassword || void 0 } : void 0, this.useProxy = t.enabled, this.currentSrc && this.load(this.currentSrc);
|
|
211
241
|
}
|
|
212
242
|
async enterVR() {
|
|
213
|
-
var
|
|
243
|
+
var e;
|
|
214
244
|
const t = this.scene.vrButton;
|
|
215
|
-
(
|
|
245
|
+
(e = t == null ? void 0 : t.click) == null || e.call(t);
|
|
216
246
|
}
|
|
217
247
|
get three() {
|
|
218
248
|
return { renderer: this.scene.renderer, scene: this.scene.scene, camera: this.scene.camera };
|
|
219
249
|
}
|
|
220
|
-
on(t,
|
|
221
|
-
let
|
|
222
|
-
return
|
|
250
|
+
on(t, e) {
|
|
251
|
+
let s = this.listeners.get(t);
|
|
252
|
+
return s || (s = /* @__PURE__ */ new Set(), this.listeners.set(t, s)), s.add(e), this;
|
|
223
253
|
}
|
|
224
|
-
off(t,
|
|
225
|
-
var
|
|
226
|
-
return (
|
|
254
|
+
off(t, e) {
|
|
255
|
+
var s;
|
|
256
|
+
return (s = this.listeners.get(t)) == null || s.delete(e), this;
|
|
227
257
|
}
|
|
228
|
-
emit(t,
|
|
229
|
-
var
|
|
230
|
-
(
|
|
258
|
+
emit(t, e) {
|
|
259
|
+
var s;
|
|
260
|
+
(s = this.listeners.get(t)) == null || s.forEach((p) => p(e));
|
|
231
261
|
}
|
|
232
262
|
persist() {
|
|
233
263
|
if (this.opts.persistSettings)
|
|
234
264
|
try {
|
|
235
|
-
localStorage.setItem(
|
|
265
|
+
localStorage.setItem(V, JSON.stringify(this.view));
|
|
236
266
|
} catch {
|
|
237
267
|
}
|
|
238
268
|
}
|
|
239
269
|
loadSettings() {
|
|
240
270
|
try {
|
|
241
|
-
const t = localStorage.getItem(
|
|
271
|
+
const t = localStorage.getItem(V);
|
|
242
272
|
return t ? JSON.parse(t) : null;
|
|
243
273
|
} catch {
|
|
244
274
|
return null;
|
|
@@ -249,12 +279,12 @@ class H {
|
|
|
249
279
|
(t = this.ui) == null || t.dispose(), this.look.dispose(), this.source.dispose(), this.scene.dispose(), this.video.remove(), this.canvas.remove(), this.wrap.remove(), this.listeners.clear();
|
|
250
280
|
}
|
|
251
281
|
}
|
|
252
|
-
class
|
|
282
|
+
class et extends HTMLElement {
|
|
253
283
|
static get observedAttributes() {
|
|
254
284
|
return ["src", "projection"];
|
|
255
285
|
}
|
|
256
286
|
connectedCallback() {
|
|
257
|
-
this.player || (this.style.display || (this.style.display = "block"), this.player = new
|
|
287
|
+
this.player || (this.style.display || (this.style.display = "block"), this.player = new tt(this, {
|
|
258
288
|
src: this.getAttribute("src") ?? void 0,
|
|
259
289
|
projection: this.getAttribute("projection") ?? void 0,
|
|
260
290
|
controls: this.hasAttribute("controls"),
|
|
@@ -265,39 +295,39 @@ class K extends HTMLElement {
|
|
|
265
295
|
proxy: this.getAttribute("proxy-url") ? { url: this.getAttribute("proxy-url"), apiPassword: this.getAttribute("proxy-password") ?? void 0 } : void 0
|
|
266
296
|
}));
|
|
267
297
|
}
|
|
268
|
-
attributeChangedCallback(t,
|
|
269
|
-
!this.player ||
|
|
298
|
+
attributeChangedCallback(t, e, s) {
|
|
299
|
+
!this.player || s == null || (t === "src" && this.player.load(s), t === "projection" && this.player.setProjection(s));
|
|
270
300
|
}
|
|
271
301
|
disconnectedCallback() {
|
|
272
302
|
var t;
|
|
273
303
|
(t = this.player) == null || t.dispose(), this.player = void 0;
|
|
274
304
|
}
|
|
275
305
|
numAttr(t) {
|
|
276
|
-
const
|
|
277
|
-
return
|
|
306
|
+
const e = this.getAttribute(t);
|
|
307
|
+
return e == null ? void 0 : Number(e);
|
|
278
308
|
}
|
|
279
309
|
/** The underlying Player instance (for programmatic control). */
|
|
280
310
|
get api() {
|
|
281
311
|
return this.player;
|
|
282
312
|
}
|
|
283
313
|
}
|
|
284
|
-
function
|
|
285
|
-
typeof customElements < "u" && !customElements.get(l) && customElements.define(l,
|
|
314
|
+
function st(l = "three-video") {
|
|
315
|
+
typeof customElements < "u" && !customElements.get(l) && customElements.define(l, et);
|
|
286
316
|
}
|
|
287
|
-
|
|
317
|
+
st();
|
|
288
318
|
export {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
319
|
+
K as LookControls,
|
|
320
|
+
rt as MODES,
|
|
321
|
+
Y as PROJECTIONS,
|
|
322
|
+
tt as Player,
|
|
323
|
+
H as StereoScene,
|
|
324
|
+
et as ThreeVideoElement,
|
|
325
|
+
_ as VideoSource,
|
|
326
|
+
X as buildProxyUrl,
|
|
327
|
+
at as clampAngles,
|
|
328
|
+
pt as detectFormat,
|
|
329
|
+
Q as detectProjection,
|
|
330
|
+
lt as isFlatMode,
|
|
331
|
+
st as registerWebComponent
|
|
302
332
|
};
|
|
303
333
|
//# sourceMappingURL=three-vr-player.js.map
|