1
0
Files
VR-Web-Player/src/vr180player/vr-controller-interactions.ts
2026-06-10 11:37:02 +10:00

110 lines
2.8 KiB
TypeScript

import * as THREE from 'https://unpkg.com/three/build/three.module.js';
import {
getSeekProgressFromIntersection,
type VrControlPanel
} from './vr-control-panel.js';
type VrControllerSelectionOptions = {
exitVr: () => void;
forward: () => void;
hidePanel: () => void;
isPanelVisible: () => boolean;
raycaster: any;
rewind: () => void;
seek: (progress: number) => void;
showPanel: () => void;
toggleMute: () => void;
togglePlayPause: () => void;
uiElements: any[];
vrPanel: VrControlPanel | undefined;
};
const tempMatrix = new THREE.Matrix4();
export function createVrController(scene: any, renderer: any, onSelectStart: (event: any) => void): {
controller: any;
raycaster: any;
} {
const controller = renderer.xr.getController(0);
controller.addEventListener('selectstart', onSelectStart);
const lineMaterial = new THREE.LineBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.5 });
const lineGeometry = new THREE.BufferGeometry().setFromPoints([
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 0, -5)
]);
controller.add(new THREE.Line(lineGeometry, lineMaterial));
scene.add(controller);
const raycaster = new THREE.Raycaster();
raycaster.near = 0.1;
raycaster.far = 5;
return { controller, raycaster };
}
export function handleVrControllerSelect(event: any, options: VrControllerSelectionOptions): void {
const controller = event.target;
if (!options.raycaster) return;
controller.updateMatrixWorld();
tempMatrix.identity().extractRotation(controller.matrixWorld);
options.raycaster.ray.origin.setFromMatrixPosition(controller.matrixWorld);
options.raycaster.ray.direction.set(0, 0, -1).applyMatrix4(tempMatrix);
const directIntersects = options.raycaster.intersectObjects(options.uiElements, true);
if (directIntersects.length === 0) {
togglePanel(options);
return;
}
const firstIntersected = directIntersects[0].object;
const intersectionPoint = directIntersects[0].point;
if (firstIntersected.name === 'vrPlayPauseButton') {
options.togglePlayPause();
options.showPanel();
return;
}
if (firstIntersected.name === 'vrRewindButton') {
options.rewind();
options.showPanel();
return;
}
if (firstIntersected.name === 'vrForwardButton') {
options.forward();
options.showPanel();
return;
}
if (firstIntersected.name === 'vrExitButton') {
options.exitVr();
options.showPanel();
return;
}
if (firstIntersected.name === 'vrVolumeButton') {
options.toggleMute();
options.showPanel();
return;
}
if (firstIntersected.name === 'seekBarHitArea') {
options.showPanel();
options.seek(getSeekProgressFromIntersection(options.vrPanel, intersectionPoint));
return;
}
togglePanel(options);
}
function togglePanel(options: VrControllerSelectionOptions): void {
if (options.isPanelVisible()) {
options.hidePanel();
} else {
options.showPanel();
}
}