pages235/renderer/viewer/lib/viewerWrapper.ts
Vitaly 65af9a73c2
feat: rework hand! enable by default, fix bow anim (#261)
* refactor swing animation to controller

* idle animator!!!!

* implelment state switch transition

* a huge fix for UI server edit!

* adjust ui scaling so main menu elements clip less

* view bobbing, new config name, ws:

* EXTREMELY important fixes to entities rendering

* a lot of fixes, add dns resolve fallback

* improve f3 E, fix modal not found edge case

* set correctly target for old browsers, should fix ios 14 crash

* unecessary big refactor, to fix ts err

* fix isWysiwyg check

* fix entities rendering count
2025-02-15 05:14:36 +03:00

120 lines
3.7 KiB
TypeScript

import * as THREE from 'three'
import { statsEnd, statsStart } from '../../../src/topRightStats'
// wrapper for now
export class ViewerWrapper {
previousWindowWidth: number
previousWindowHeight: number
globalObject = globalThis as any
stopRenderOnBlur = false
addedToPage = false
renderInterval = 0
renderIntervalUnfocused: number | undefined
fpsInterval
constructor (public canvas: HTMLCanvasElement, public renderer?: THREE.WebGLRenderer) {
if (this.renderer) this.globalObject.renderer = this.renderer
}
addToPage (startRendering = true) {
if (this.addedToPage) throw new Error('Already added to page')
let pixelRatio = window.devicePixelRatio || 1 // todo this value is too high on ios, need to check, probably we should use avg, also need to make it configurable
if (this.renderer) {
if (!this.renderer.capabilities.isWebGL2) pixelRatio = 1 // webgl1 has issues with high pixel ratio (sometimes screen is clipped)
this.renderer.setPixelRatio(pixelRatio)
this.renderer.setSize(window.innerWidth, window.innerHeight)
} else {
this.canvas.width = window.innerWidth * pixelRatio
this.canvas.height = window.innerHeight * pixelRatio
}
this.previousWindowWidth = window.innerWidth
this.previousWindowHeight = window.innerHeight
this.canvas.id = 'viewer-canvas'
document.body.appendChild(this.canvas)
this.addedToPage = true
let max = 0
this.fpsInterval = setInterval(() => {
if (max > 0) {
viewer.world.droppedFpsPercentage = this.renderedFps / max
}
max = Math.max(this.renderedFps, max)
this.renderedFps = 0
}, 1000)
if (startRendering) {
this.globalObject.requestAnimationFrame(this.render.bind(this))
}
if (typeof window !== 'undefined') {
this.trackWindowFocus()
}
}
windowFocused = true
trackWindowFocus () {
window.addEventListener('focus', () => {
this.windowFocused = true
})
window.addEventListener('blur', () => {
this.windowFocused = false
})
}
dispose () {
if (!this.addedToPage) throw new Error('Not added to page')
this.canvas.remove()
this.renderer?.dispose()
// this.addedToPage = false
clearInterval(this.fpsInterval)
}
renderedFps = 0
lastTime = performance.now()
delta = 0
preRender = () => { }
postRender = () => { }
render (time: DOMHighResTimeStamp) {
if (this.globalObject.stopLoop) return
for (const fn of beforeRenderFrame) fn()
this.globalObject.requestAnimationFrame(this.render.bind(this))
if (!viewer || this.globalObject.stopRender || this.renderer?.xr.isPresenting || (this.stopRenderOnBlur && !this.windowFocused)) return
const renderInterval = (this.windowFocused ? this.renderInterval : this.renderIntervalUnfocused) ?? this.renderInterval
if (renderInterval) {
this.delta += time - this.lastTime
this.lastTime = time
if (this.delta > renderInterval) {
this.delta %= renderInterval
// continue rendering
} else {
return
}
}
this.preRender()
statsStart()
// ios bug: viewport dimensions are updated after the resize event
if (this.previousWindowWidth !== window.innerWidth || this.previousWindowHeight !== window.innerHeight) {
this.resizeHandler()
this.previousWindowWidth = window.innerWidth
this.previousWindowHeight = window.innerHeight
}
viewer.render()
this.renderedFps++
statsEnd()
this.postRender()
}
resizeHandler () {
const width = window.innerWidth
const height = window.innerHeight
viewer.camera.aspect = width / height
viewer.camera.updateProjectionMatrix()
if (this.renderer) {
this.renderer.setSize(width, height)
}
viewer.world.handleResize()
}
}