forked from EXT/VR180-Web-Player
122 lines
2.9 KiB
TypeScript
122 lines
2.9 KiB
TypeScript
import {
|
|
hideVrPanelImmediately,
|
|
setVrPanelOpacity,
|
|
type VrControlPanel
|
|
} from './vr-control-panel.js';
|
|
import { DEFAULT_MENU_AUTO_HIDE_DELAY_MS } from '../utils/control-panel-timing.js';
|
|
|
|
const FADE_DURATION_MS = 200;
|
|
|
|
export class VrPanelVisibility {
|
|
private hideTimeout: number | undefined;
|
|
private lastFadeTimestamp = 0;
|
|
private opacity = 0;
|
|
private panel: VrControlPanel | undefined;
|
|
private targetOpacity = 0;
|
|
private fading = false;
|
|
|
|
get isFading(): boolean {
|
|
return this.fading;
|
|
}
|
|
|
|
get isVisible(): boolean {
|
|
return !!(this.panel?.group.visible && this.opacity > 0.01);
|
|
}
|
|
|
|
setPanel(panel: VrControlPanel): void {
|
|
this.panel = panel;
|
|
this.hideImmediately();
|
|
}
|
|
|
|
show(autoHideDelayMs = DEFAULT_MENU_AUTO_HIDE_DELAY_MS): void {
|
|
this.showWithAutoHide(true, autoHideDelayMs);
|
|
}
|
|
|
|
showPersistent(): void {
|
|
this.showWithAutoHide(false, DEFAULT_MENU_AUTO_HIDE_DELAY_MS);
|
|
}
|
|
|
|
private showWithAutoHide(shouldAutoHide: boolean, autoHideDelayMs: number): void {
|
|
if (this.panel) this.panel.group.visible = true;
|
|
this.clearHideTimeout();
|
|
|
|
if (this.targetOpacity !== 1.0 || this.opacity < 1.0) {
|
|
this.targetOpacity = 1.0;
|
|
this.startFade();
|
|
}
|
|
|
|
if (shouldAutoHide) {
|
|
this.hideTimeout = window.setTimeout(() => this.hide(), autoHideDelayMs);
|
|
}
|
|
}
|
|
|
|
hide(): void {
|
|
this.clearHideTimeout();
|
|
|
|
if (this.targetOpacity !== 0.0 || this.opacity > 0.0) {
|
|
this.targetOpacity = 0.0;
|
|
this.startFade();
|
|
}
|
|
}
|
|
|
|
hideImmediately(): void {
|
|
this.clearHideTimeout();
|
|
this.targetOpacity = 0;
|
|
this.opacity = 0;
|
|
this.fading = false;
|
|
hideVrPanelImmediately(this.panel);
|
|
}
|
|
|
|
updateFade(timestamp: number): void {
|
|
if (!this.panel) return;
|
|
if (this.lastFadeTimestamp === 0) this.lastFadeTimestamp = timestamp;
|
|
|
|
const deltaTime = (timestamp - this.lastFadeTimestamp) / 1000;
|
|
this.lastFadeTimestamp = timestamp;
|
|
const fadeSpeed = 1 / (FADE_DURATION_MS / 1000);
|
|
let opacityChanged = false;
|
|
|
|
if (this.opacity < this.targetOpacity) {
|
|
this.opacity += fadeSpeed * deltaTime;
|
|
if (this.opacity >= this.targetOpacity) {
|
|
this.opacity = this.targetOpacity;
|
|
this.fading = false;
|
|
}
|
|
opacityChanged = true;
|
|
} else if (this.opacity > this.targetOpacity) {
|
|
this.opacity -= fadeSpeed * deltaTime;
|
|
if (this.opacity <= this.targetOpacity) {
|
|
this.opacity = this.targetOpacity;
|
|
this.fading = false;
|
|
if (this.opacity === 0) this.panel.group.visible = false;
|
|
}
|
|
opacityChanged = true;
|
|
} else {
|
|
this.fading = false;
|
|
}
|
|
|
|
if (opacityChanged) {
|
|
setVrPanelOpacity(this.panel, this.opacity);
|
|
}
|
|
|
|
if (this.fading) {
|
|
requestAnimationFrame((nextTimestamp) => this.updateFade(nextTimestamp));
|
|
}
|
|
}
|
|
|
|
private clearHideTimeout(): void {
|
|
if (this.hideTimeout !== undefined) {
|
|
clearTimeout(this.hideTimeout);
|
|
this.hideTimeout = undefined;
|
|
}
|
|
}
|
|
|
|
private startFade(): void {
|
|
if (!this.fading) {
|
|
this.fading = true;
|
|
this.lastFadeTimestamp = 0;
|
|
requestAnimationFrame((timestamp) => this.updateFade(timestamp));
|
|
}
|
|
}
|
|
}
|