UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

124 lines (111 loc) 3.63 kB
import {PolyScene} from '../PolyScene'; import {Poly} from '../../Poly'; import {AbstractRenderer} from '../../viewers/Common'; import {WebGLRenderer} from 'three'; import type {PathTracingRendererContainer} from '../../nodes/rop/utils/pathTracing/PathTracingRendererContainer'; import {arrayCopy} from '../../../core/ArrayUtils'; type SceneRenderersRegisterCallback = (value: AbstractRenderer) => void; export interface RegisterRendererOptions { assignId: boolean; } const _renderers: AbstractRenderer[] = []; export class SceneRenderersRegister { private _renderersById: Map<number, AbstractRenderer> = new Map(); private _registerTimeByRenderer: Map<AbstractRenderer, number> = new Map(); private _lastRegisteredRenderer: AbstractRenderer | undefined; private _resolves: SceneRenderersRegisterCallback[] = []; constructor(protected scene: PolyScene) {} registerRenderer(renderer: AbstractRenderer, options?: RegisterRendererOptions) { let assignId = true; if (options?.assignId == false) { assignId = false; } if (assignId) { Poly.renderersController.assignIdToRenderer(renderer); } const id = Poly.renderersController.rendererId(renderer); if (id == null) { return; } this._renderersById.set(id, renderer); this._registerTimeByRenderer.set(renderer, performance.now()); // Poly.renderersController._registerRenderer(renderer, this.scene); this._updateCache(); if (this._renderersById.size == 1) { this._flushCallbacksWithRenderer(renderer); } } dispose() { this.renderers(_renderers); for (const renderer of _renderers) { this.deregisterRenderer(renderer); } } deregisterRenderer(renderer: AbstractRenderer) { const id = Poly.renderersController.rendererId(renderer); if (id == null) { return; } this._renderersById.delete(id); renderer.dispose(); this._updateCache(); // Poly.renderersController._deregisterRenderer(renderer); } lastRegisteredRenderer() { return this._lastRegisteredRenderer; } renderers(target: AbstractRenderer[]) { // const renderers: AbstractRenderer[] = []; this._renderersById.forEach((renderer) => { target.push(renderer); }); return target; } private _updateCache() { this._lastRegisteredRenderer = undefined; this._registerTimeByRenderer.forEach((registerTime, renderer) => { if (this._lastRegisteredRenderer == undefined) { this._lastRegisteredRenderer = renderer; } else { const lastRegisterTime = this._registerTimeByRenderer.get(this._lastRegisteredRenderer); if (lastRegisterTime != null) { if (registerTime > lastRegisterTime) { this._lastRegisteredRenderer = renderer; } } } }); } private _flushCallbacksWithRenderer(renderer: AbstractRenderer) { const callbacks: SceneRenderersRegisterCallback[] = []; arrayCopy(this._resolves, callbacks); this._resolves.length = 0; for (const c of callbacks) { c(renderer); } } async waitForAbstractRenderer(): Promise<AbstractRenderer> { if (this._lastRegisteredRenderer) { return this._lastRegisteredRenderer; } else { return new Promise((resolve, reject) => { this._resolves.push(resolve); }); } } async waitForRenderer(): Promise<WebGLRenderer | undefined> { let renderer = await this.waitForAbstractRenderer(); if (renderer instanceof WebGLRenderer) { return renderer; } renderer = (renderer as PathTracingRendererContainer).webGLRenderer; if (renderer && renderer instanceof WebGLRenderer) { return renderer; } if (renderer) { if (!(renderer instanceof WebGLRenderer)) { console.log('unexpected renderer:', {renderer}); } } } }