forked from EXT/VR180-Web-Player
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
import {
|
||||
DEFAULT_PROJECTION,
|
||||
PLANE_2D_DISTANCE,
|
||||
PLANE_DISTANCE,
|
||||
PLAYER_SELECTOR,
|
||||
type ProjectionMode,
|
||||
VALID_PROJECTIONS
|
||||
type ProjectionMode
|
||||
} from './config.js';
|
||||
import { bootstrapPlayer } from './bootstrap.js';
|
||||
import { createContentScene } from './rendering/content-scene.js';
|
||||
import { create2DControlPanel, createPlayButton, injectPlayerStyles } from './dom/dom.js';
|
||||
import {
|
||||
applySbsTextureWindow as applySbsTextureWindowCore,
|
||||
hideContentMeshes as hideContentMeshesCore,
|
||||
@@ -35,11 +32,12 @@ import {
|
||||
createPlayerRenderer,
|
||||
resizePlayerRenderer
|
||||
} from './rendering/renderer-lifecycle.js';
|
||||
import { VideoTextureManager } from './rendering/texture-manager.js';
|
||||
|
||||
const _playerBase = new URL('.', import.meta.url).href;
|
||||
|
||||
let playerContainer, projectionMode: ProjectionMode = DEFAULT_PROJECTION;
|
||||
let scene, camera, renderer, video, videoTexture, sphereMaterial;
|
||||
let playerContainer, projectionMode: ProjectionMode;
|
||||
let scene, camera, renderer, video, sphereMaterial;
|
||||
let vr180Mesh, planeMesh, activeContentMesh;
|
||||
let xrSession = null;
|
||||
let raycaster, uiElements = [];
|
||||
@@ -49,6 +47,7 @@ let frameCounter = 0;
|
||||
let isXrLoopActive = false;
|
||||
let vrControlPanel;
|
||||
let mediaController: MediaController | undefined;
|
||||
let textureManager: VideoTextureManager | undefined;
|
||||
let vrPanel: VrControlPanel | undefined;
|
||||
let twoDMode: TwoDMode | undefined;
|
||||
const vrPanelVisibility = new VrPanelVisibility();
|
||||
@@ -57,82 +56,15 @@ const vrPanelVisibility = new VrPanelVisibility();
|
||||
let camera2D;
|
||||
let fallbackCameraControls: FallbackCameraControls | undefined;
|
||||
|
||||
injectPlayerStyles(_playerBase);
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const containers = document.querySelectorAll(PLAYER_SELECTOR);
|
||||
|
||||
if (containers.length === 0) {
|
||||
console.error(`VR_WEB_PLAYER_DOM: Expected exactly one ${PLAYER_SELECTOR} container, found none.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (containers.length > 1) {
|
||||
console.warn(`VR_WEB_PLAYER_DOM: This version supports exactly one ${PLAYER_SELECTOR} container per page. Found ${containers.length}; no player was initialized.`);
|
||||
return;
|
||||
}
|
||||
|
||||
playerContainer = containers[0];
|
||||
playerContainer.classList.add('vrwp');
|
||||
|
||||
const configuredProjection = (playerContainer.dataset.projection || DEFAULT_PROJECTION).trim().toLowerCase();
|
||||
if (!VALID_PROJECTIONS.has(configuredProjection as ProjectionMode)) {
|
||||
console.error(`VR_WEB_PLAYER_CONFIG: Unsupported data-projection="${configuredProjection}". Use "vr180" or "plane".`);
|
||||
return;
|
||||
}
|
||||
projectionMode = configuredProjection as ProjectionMode;
|
||||
|
||||
videoElement = playerContainer.querySelector('video');
|
||||
if (!videoElement) {
|
||||
console.error(`VR_WEB_PLAYER_DOM: ${PLAYER_SELECTOR} must contain a video element.`);
|
||||
return;
|
||||
}
|
||||
videoElement.classList.add('vrwp-video');
|
||||
|
||||
// Create and insert play button
|
||||
playBtn = createPlayButton();
|
||||
playerContainer.appendChild(playBtn);
|
||||
|
||||
// Create and insert 2D control panel
|
||||
const controlPanel = create2DControlPanel();
|
||||
playerContainer.appendChild(controlPanel);
|
||||
|
||||
playBtn.disabled = true;
|
||||
|
||||
if (videoElement) {
|
||||
videoElement.load();
|
||||
}
|
||||
|
||||
if (navigator.xr) {
|
||||
navigator.xr.isSessionSupported('immersive-vr').then((supported) => {
|
||||
if (supported) {
|
||||
playBtn.dataset.xrSupported = "true";
|
||||
} else {
|
||||
playBtn.dataset.xrSupported = "false";
|
||||
// Enable button for regular video playback when VR is not supported
|
||||
playBtn.disabled = false;
|
||||
}
|
||||
// Always call init() regardless of VR support
|
||||
init();
|
||||
}).catch(err => {
|
||||
console.error("XR Support Check Error:", err);
|
||||
playBtn.dataset.xrSupported = "false";
|
||||
// Enable button for regular video playback when VR check fails
|
||||
playBtn.disabled = false;
|
||||
// Call init() even when VR check fails
|
||||
init();
|
||||
});
|
||||
} else {
|
||||
playBtn.dataset.xrSupported = "false";
|
||||
// If navigator.xr itself is not available, enable button for regular video playback
|
||||
if (playBtn) {
|
||||
playBtn.disabled = false;
|
||||
}
|
||||
// Call init() even when XR is not available
|
||||
init();
|
||||
}
|
||||
bootstrapPlayer(_playerBase, (context) => {
|
||||
playerContainer = context.playerContainer;
|
||||
projectionMode = context.projectionMode;
|
||||
videoElement = context.videoElement;
|
||||
playBtn = context.playButton;
|
||||
init();
|
||||
});
|
||||
|
||||
|
||||
function applySbsTextureWindow(renderingRenderer, activeCamera, material) {
|
||||
applySbsTextureWindowCore(renderingRenderer, activeCamera, material, is2DModeActive());
|
||||
}
|
||||
@@ -150,9 +82,10 @@ function positionPlaneForPresentation(isFallback2D = false) {
|
||||
}
|
||||
|
||||
function createVideoTexture() {
|
||||
if (videoTexture) videoTexture.dispose();
|
||||
videoTexture = createVideoTextureCore(video);
|
||||
return videoTexture;
|
||||
if (!textureManager) {
|
||||
throw new Error('Video texture manager is not initialized.');
|
||||
}
|
||||
return textureManager.create();
|
||||
}
|
||||
|
||||
function is2DModeActive() {
|
||||
@@ -174,9 +107,7 @@ function closeActiveXrSessionAfterContextLoss() {
|
||||
|
||||
function restoreVideoTextureAfterContextRestored() {
|
||||
if (video && sphereMaterial && activeContentMesh && activeContentMesh.visible && renderer.xr.isPresenting && xrSession) {
|
||||
videoTexture = createVideoTexture();
|
||||
sphereMaterial.map = videoTexture;
|
||||
sphereMaterial.needsUpdate = true;
|
||||
textureManager?.assignToMaterial(sphereMaterial);
|
||||
updateVRPlayPauseButtonIcon();
|
||||
updateVRVolumeButtonIcon();
|
||||
console.log("Re-initialized video texture after context restoration during VR.");
|
||||
@@ -202,6 +133,7 @@ function init() {
|
||||
renderer = playerRenderer.renderer;
|
||||
|
||||
video = videoElement;
|
||||
textureManager = new VideoTextureManager(video, createVideoTextureCore);
|
||||
mediaController = new MediaController({
|
||||
is2DModeActive,
|
||||
on2DPlaybackResume: show2DControlPanel,
|
||||
@@ -502,17 +434,18 @@ async function actualSessionToggle() {
|
||||
if (camera) camera.updateProjectionMatrix();
|
||||
positionPlaneForPresentation(false);
|
||||
|
||||
if (videoTexture) { videoTexture.dispose(); videoTexture = null; }
|
||||
if (video) {
|
||||
videoTexture = createVideoTexture();
|
||||
if (activeContentMesh && sphereMaterial) {
|
||||
sphereMaterial.map = videoTexture;
|
||||
sphereMaterial.needsUpdate = true;
|
||||
showActiveContentMesh();
|
||||
} else { throw new Error("VR mesh components not ready for texture."); }
|
||||
} else {
|
||||
textureManager?.dispose();
|
||||
if (!video) {
|
||||
throw new Error("Video element not available for creating texture.");
|
||||
}
|
||||
if (!activeContentMesh || !sphereMaterial) {
|
||||
throw new Error("VR mesh components not ready for texture.");
|
||||
}
|
||||
if (!textureManager) {
|
||||
throw new Error("Video texture manager is not initialized.");
|
||||
}
|
||||
textureManager.assignToMaterial(sphereMaterial);
|
||||
showActiveContentMesh();
|
||||
|
||||
updateVRPlayPauseButtonIcon();
|
||||
updateVRVolumeButtonIcon();
|
||||
@@ -531,8 +464,7 @@ async function actualSessionToggle() {
|
||||
isXrLoopActive = false;
|
||||
|
||||
hideContentMeshes();
|
||||
if (sphereMaterial) { sphereMaterial.map = null; sphereMaterial.needsUpdate = true; }
|
||||
if (videoTexture) { videoTexture.dispose(); videoTexture = null; }
|
||||
textureManager?.clearMaterial(sphereMaterial);
|
||||
if (vrControlPanel) {
|
||||
vrPanelVisibility.hideImmediately();
|
||||
}
|
||||
@@ -570,14 +502,7 @@ function onVRSessionEnd(event) {
|
||||
|
||||
mediaController?.pauseIfPlaying();
|
||||
|
||||
if (sphereMaterial && sphereMaterial.map) {
|
||||
sphereMaterial.map.dispose();
|
||||
sphereMaterial.map = null;
|
||||
sphereMaterial.needsUpdate = true;
|
||||
}
|
||||
if (videoTexture) {
|
||||
videoTexture.dispose(); videoTexture = null;
|
||||
}
|
||||
textureManager?.clearMaterial(sphereMaterial);
|
||||
hideContentMeshes();
|
||||
if (vrControlPanel) {
|
||||
vrPanelVisibility.hideImmediately();
|
||||
@@ -633,10 +558,7 @@ function renderXR(timestamp, frame) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Sync video texture before render to ensure frame consistency
|
||||
if (videoTexture && video && !video.paused && !video.ended) {
|
||||
videoTexture.needsUpdate = true;
|
||||
}
|
||||
textureManager?.updateIfPlaying();
|
||||
renderer.render(scene, camera);
|
||||
} catch (error) {
|
||||
const renderErrorMsg = "ERROR_IN_RENDERXR_LOOP (F" + frameCounter + "): " + (error.message || String(error));
|
||||
|
||||
Reference in New Issue
Block a user