forked from EXT/VR180-Web-Player
Seperation
This commit is contained in:
168
src/vr180player/fallback-camera-controls.ts
Normal file
168
src/vr180player/fallback-camera-controls.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import type { ProjectionMode } from './config.js';
|
||||
|
||||
type CameraControlsCallbacks = {
|
||||
hideControls: () => void;
|
||||
isEnabled: () => boolean;
|
||||
showControls: () => void;
|
||||
};
|
||||
|
||||
const MOUSE_SENSITIVITY = 0.002;
|
||||
const TOUCH_SENSITIVITY = 0.003;
|
||||
const MOMENTUM_DAMPING = 0.8;
|
||||
const MAX_PITCH = Math.PI * (45 / 180);
|
||||
const MAX_YAW = Math.PI * (45 / 180);
|
||||
|
||||
export class FallbackCameraControls {
|
||||
private camera: any;
|
||||
private readonly callbacks: CameraControlsCallbacks;
|
||||
private cameraRotation = { yaw: 0, pitch: 0 };
|
||||
private cameraVelocity = { yaw: 0, pitch: 0 };
|
||||
private dragging = false;
|
||||
private lastMouseX = 0;
|
||||
private lastMouseY = 0;
|
||||
private lastTouchX = 0;
|
||||
private lastTouchY = 0;
|
||||
|
||||
constructor(camera: any, callbacks: CameraControlsCallbacks) {
|
||||
this.camera = camera;
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
get isDragging(): boolean {
|
||||
return this.dragging;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.cameraRotation = { yaw: 0, pitch: 0 };
|
||||
this.cameraVelocity = { yaw: 0, pitch: 0 };
|
||||
this.dragging = false;
|
||||
if (this.camera) {
|
||||
this.camera.rotation.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
updateCameraRotation(): void {
|
||||
if (!this.camera) return;
|
||||
|
||||
this.cameraRotation.yaw += this.cameraVelocity.yaw;
|
||||
this.cameraRotation.pitch += this.cameraVelocity.pitch;
|
||||
|
||||
this.cameraRotation.pitch = Math.max(-MAX_PITCH, Math.min(MAX_PITCH, this.cameraRotation.pitch));
|
||||
this.cameraRotation.yaw = Math.max(-MAX_YAW, Math.min(MAX_YAW, this.cameraRotation.yaw));
|
||||
|
||||
this.cameraVelocity.yaw *= MOMENTUM_DAMPING;
|
||||
this.cameraVelocity.pitch *= MOMENTUM_DAMPING;
|
||||
|
||||
if (Math.abs(this.cameraVelocity.yaw) < 0.001) this.cameraVelocity.yaw = 0;
|
||||
if (Math.abs(this.cameraVelocity.pitch) < 0.001) this.cameraVelocity.pitch = 0;
|
||||
|
||||
this.camera.rotation.set(this.cameraRotation.pitch, this.cameraRotation.yaw, 0);
|
||||
}
|
||||
|
||||
addEventListeners(canvas: HTMLElement, projectionMode: ProjectionMode): void {
|
||||
canvas.addEventListener('mousemove', this.onCanvasMouseMove);
|
||||
|
||||
if (projectionMode === 'vr180') {
|
||||
canvas.addEventListener('mousedown', this.onMouseDown);
|
||||
canvas.addEventListener('mousemove', this.onMouseMove);
|
||||
canvas.addEventListener('mouseup', this.onMouseUp);
|
||||
canvas.addEventListener('touchstart', this.onTouchStart, { passive: false });
|
||||
canvas.addEventListener('touchmove', this.onTouchMove, { passive: false });
|
||||
canvas.addEventListener('touchend', this.onTouchEnd, { passive: false });
|
||||
} else {
|
||||
canvas.addEventListener('touchstart', this.onCanvasTouchStart, { passive: true });
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListeners(canvas: HTMLElement): void {
|
||||
canvas.removeEventListener('mousemove', this.onCanvasMouseMove);
|
||||
canvas.removeEventListener('mousedown', this.onMouseDown);
|
||||
canvas.removeEventListener('mousemove', this.onMouseMove);
|
||||
canvas.removeEventListener('mouseup', this.onMouseUp);
|
||||
canvas.removeEventListener('touchstart', this.onTouchStart);
|
||||
canvas.removeEventListener('touchmove', this.onTouchMove);
|
||||
canvas.removeEventListener('touchend', this.onTouchEnd);
|
||||
canvas.removeEventListener('touchstart', this.onCanvasTouchStart);
|
||||
}
|
||||
|
||||
private readonly onCanvasMouseMove = (): void => {
|
||||
if (this.callbacks.isEnabled() && !this.dragging) {
|
||||
this.callbacks.showControls();
|
||||
}
|
||||
};
|
||||
|
||||
private readonly onCanvasTouchStart = (): void => {
|
||||
if (this.callbacks.isEnabled()) {
|
||||
this.callbacks.showControls();
|
||||
}
|
||||
};
|
||||
|
||||
private readonly onMouseDown = (event: MouseEvent): void => {
|
||||
if (!this.callbacks.isEnabled()) return;
|
||||
|
||||
this.dragging = true;
|
||||
this.lastMouseX = event.clientX;
|
||||
this.lastMouseY = event.clientY;
|
||||
this.cameraVelocity.yaw = 0;
|
||||
this.cameraVelocity.pitch = 0;
|
||||
this.callbacks.hideControls();
|
||||
};
|
||||
|
||||
private readonly onMouseMove = (event: MouseEvent): void => {
|
||||
if (!this.callbacks.isEnabled() || !this.dragging) return;
|
||||
|
||||
const deltaX = event.clientX - this.lastMouseX;
|
||||
const deltaY = event.clientY - this.lastMouseY;
|
||||
|
||||
this.cameraVelocity.yaw = deltaX * MOUSE_SENSITIVITY;
|
||||
this.cameraVelocity.pitch = deltaY * MOUSE_SENSITIVITY;
|
||||
|
||||
this.lastMouseX = event.clientX;
|
||||
this.lastMouseY = event.clientY;
|
||||
};
|
||||
|
||||
private readonly onMouseUp = (): void => {
|
||||
if (!this.callbacks.isEnabled()) return;
|
||||
|
||||
this.dragging = false;
|
||||
this.callbacks.showControls();
|
||||
};
|
||||
|
||||
private readonly onTouchStart = (event: TouchEvent): void => {
|
||||
if (!this.callbacks.isEnabled()) return;
|
||||
|
||||
event.preventDefault();
|
||||
if (event.touches.length === 1) {
|
||||
this.dragging = true;
|
||||
this.lastTouchX = event.touches[0].clientX;
|
||||
this.lastTouchY = event.touches[0].clientY;
|
||||
this.cameraVelocity.yaw = 0;
|
||||
this.cameraVelocity.pitch = 0;
|
||||
this.callbacks.hideControls();
|
||||
}
|
||||
};
|
||||
|
||||
private readonly onTouchMove = (event: TouchEvent): void => {
|
||||
if (!this.callbacks.isEnabled() || !this.dragging) return;
|
||||
|
||||
event.preventDefault();
|
||||
if (event.touches.length === 1) {
|
||||
const deltaX = event.touches[0].clientX - this.lastTouchX;
|
||||
const deltaY = event.touches[0].clientY - this.lastTouchY;
|
||||
|
||||
this.cameraVelocity.yaw = deltaX * TOUCH_SENSITIVITY;
|
||||
this.cameraVelocity.pitch = deltaY * TOUCH_SENSITIVITY;
|
||||
|
||||
this.lastTouchX = event.touches[0].clientX;
|
||||
this.lastTouchY = event.touches[0].clientY;
|
||||
}
|
||||
};
|
||||
|
||||
private readonly onTouchEnd = (event: TouchEvent): void => {
|
||||
if (!this.callbacks.isEnabled()) return;
|
||||
|
||||
event.preventDefault();
|
||||
this.dragging = false;
|
||||
this.callbacks.showControls();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user