UNPKG

@polygonjs/polygonjs

Version:

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

200 lines (199 loc) 6.72 kB
"use strict"; import { RootLoadProgressController } from "./../../nodes/manager/utils/Scene/LoadProgress"; import { isString } from "../../../core/Type"; import { TimeController } from "../../scene/utils/TimeController"; import { PolyEventsDispatcher } from "../common/EventsDispatcher"; import { PolyEventName } from "../../poly/utils/PolyEventName"; import { PROGRESS_RATIO } from "../common/Progress"; import { SceneJsonImporter } from "../json/import/Scene"; export class ScenePlayerImporter { // private _cameraCreatorNode: BaseNodeType | null = null; constructor(options) { this.options = options; this._onLoadCompleteCalled = false; this._progress = 0; this._viewerMarkedAsReady = false; this._sceneMarkedAsReady = false; this._debug2("new ScenePlayerImporter", options); } static async loadSceneData(options) { const scenePlayerImporter = new ScenePlayerImporter(options); const scene = await scenePlayerImporter.loadScene(options.serializers); return { scene, viewer: scenePlayerImporter._viewer }; } async _onLoadComplete(scene) { if (this._onLoadCompleteCalled == true) { return; } this._onLoadCompleteCalled = true; if (this._viewer) { this._markViewerAsReady(this._viewer); } await this._markSceneAsReady(scene); } _markViewerAsReady(viewer) { if (this._viewerMarkedAsReady) { return; } this._viewerMarkedAsReady = true; viewer.markAsReady(); this._dispatchEvent(PolyEventName.VIEWER_READY); } async _markSceneAsReady(scene) { if (this._sceneMarkedAsReady) { return; } this._sceneMarkedAsReady = true; await scene.cookController.waitForCooksCompleted(); scene.setFrame(TimeController.START_FRAME); if (this.options.autoPlay != false) { scene.play(); } scene.loadingController.dispatchReadyEvent(); this._dispatchEvent(PolyEventName.SCENE_READY); } _onNodesCookProgress(nodesCookProgress, args) { const progressRatio = PROGRESS_RATIO.nodes; const onProgress = (_ratio, args2) => { var _a; const progress = progressRatio.start + progressRatio.mult * _ratio; this._progress = progress; if (this.options.onProgress) { this.options.onProgress(progress, args2); } PolyEventsDispatcher.dispatchProgressEvent(progress, (_a = this._scene) == null ? void 0 : _a.name()); }; onProgress(nodesCookProgress, args); if (nodesCookProgress >= 1) { this._onLoadComplete(args.scene); } } async _watchNodesProgress(scene) { scene.root().loadProgress.watchNodesProgress((nodesCookProgress, args) => { this._onNodesCookProgress(nodesCookProgress, args); }); } async loadScene(options) { const createSceneAndWaitForCameraCreatorNode = () => { return new Promise(async (resolve) => { const configureScene = this.options.configureScene; const importer = new SceneJsonImporter(this.options.sceneData, { sceneName: this.options.sceneName, configureScene, nodeCookWatcher: (scene3) => { this._watchNodesProgress(scene3); } }); const scene2 = importer.scene(options); scene2.timeController.forbidPlayUntilAllNodesCooked(); this._scene = scene2; this._dispatchEvent(PolyEventName.SCENE_CREATED); if (this.options.renderer) { scene2.renderersRegister.registerRenderer(this.options.renderer); } const onCameraUpdated = async () => { const camera = await scene2.camerasController.mainCamera({ findAnyCamera: false, printCameraNotFoundError: this._progress >= 1, // we display a warning if progress is 1 cameraMaskOverride: this.options.cameraMaskOverride }); this._debug2("scene.camerasController:", { camera, cameraPath: scene2.root().mainCameraController.rawCameraPath() }); if (camera) { if (this._onCameraCreatorNodeLoadedResolve) { this._onCameraCreatorNodeLoadedResolve(); } } }; this._onCameraCreatorNodeLoadedResolve = () => { scene2.camerasController.removeOnCameraObjectsUpdated(onCameraUpdated); resolve(scene2); }; scene2.camerasController.onCameraObjectsUpdated(onCameraUpdated); }); }; this._scene = await createSceneAndWaitForCameraCreatorNode(); const scene = this._scene; const createViewer = async () => { const domElement = this._domElement(); let createViewer2 = false; if (this.options.createViewer != null) { createViewer2 = this.options.createViewer; } if (domElement || createViewer2) { this._viewer = await scene.camerasController.createMainViewer({ autoRender: false, renderer: this.options.renderer, cameraMaskOverride: this.options.cameraMaskOverride }); if (this._viewer) { if (domElement) { this._viewer.mount(domElement); } if (this._sceneMarkedAsReady == true) { this._markViewerAsReady(this._viewer); } this._dispatchEvent(PolyEventName.VIEWER_MOUNTED); } } }; await createViewer(); return scene; } _domElement() { const domElement = this.options.domElement; if (domElement) { if (isString(domElement)) { const element = document.getElementById(domElement); if (element) { return element; } } else { return domElement; } } } _dispatchEvent(eventName) { this._debug2("_dispatchEvent", { eventName, scene: this._scene, viewer: this._viewer }); const elements = [this._domElement(), document]; if (!this._scene) { console.warn(`no event emitted as no scene preset`); return; } const detail = { scene: this._scene, viewer: this._viewer }; const createEvent = (customEventName) => { return new CustomEvent(customEventName, { detail }); }; for (let element of elements) { if (element) { element.dispatchEvent(createEvent(eventName)); if (this._scene) { element.dispatchEvent(createEvent(`${eventName}-${this._scene.name()}`)); } } } } _debug(arg0) { ScenePlayerImporter._debug(arg0); } _debug2(arg0, arg1) { ScenePlayerImporter._debug2(arg0, arg1); } static _debug(arg0) { RootLoadProgressController.debug(arg0); } static _debug2(arg0, arg1) { RootLoadProgressController.debug2(arg0, arg1); } }