UNPKG

three-demo

Version:
227 lines (221 loc) 6.1 kB
/** * three-demo v5.1.3 build Mon Dec 06 2021 * https://github.com/vanruesc/three-demo * Copyright 2021 Raoul van Rüschen * @license Zlib */ // src/core/Demo.ts import { LoadingManager, Scene } from "three"; var Demo = class { id; renderer; loadingManager; assets; scene = new Scene(); camera; constructor(id = "demo") { this.id = id; this.renderer = null; this.loadingManager = new LoadingManager(); this.assets = /* @__PURE__ */ new Map(); this.scene = new Scene(); this.camera = null; } setRenderer(renderer) { this.renderer = renderer; return this; } getCamera() { return this.camera; } load() { return Promise.resolve(); } initialize() { } update(deltaTime, timestamp) { } render(deltaTime, timestamp) { this.renderer.render(this.scene, this.camera); } registerOptions(menu) { } dispose() { } reset() { this.scene = new Scene(); this.camera = null; return this; } }; // src/core/DemoManager.ts import { GUI } from "dat.gui"; import { EventDispatcher, OrthographicCamera, PerspectiveCamera, WebGLRenderer as WebGLRenderer2 } from "three"; // src/core/DemoManagerEvent.ts var DemoManagerEvent = class { type; previousDemo; demo; constructor(type) { this.type = type; this.previousDemo = null; this.demo = null; } }; // src/core/demo-manager-events.ts var change = new DemoManagerEvent("change"); var load = new DemoManagerEvent("load"); // src/core/DemoManager.ts var MILLISECONDS_TO_SECONDS = 1 / 1e3; var DemoManager = class extends EventDispatcher { renderer; timestamp; menu; loadedDemos; demos; currentDemo; demoId; constructor(viewport, params) { super(); const options = Object.assign({ aside: viewport, renderer: null }, params); this.renderer = options.renderer; if (this.renderer === null) { const renderer = new WebGLRenderer2(); renderer.setSize(viewport.clientWidth, viewport.clientHeight); renderer.setPixelRatio(window.devicePixelRatio); this.renderer = renderer; } this.timestamp = 0; this.menu = new GUI({ autoPlace: false }); this.loadedDemos = /* @__PURE__ */ new Set(); this.demos = /* @__PURE__ */ new Map(); this.currentDemo = null; this.demoId = null; viewport.appendChild(this.renderer.domElement); options.aside.appendChild(this.menu.domElement); } resetMenu() { const node = this.menu.domElement.parentNode; const menu = new GUI({ autoPlace: false }); if (this.demos.size > 1) { const selection = menu.add({ demo: this.demoId }, "demo", [...this.demos.keys()]); selection.onChange((value) => this.loadDemo(value)); } node.removeChild(this.menu.domElement); node.appendChild(menu.domElement); this.menu.destroy(); this.menu = menu; return menu; } startDemo(demo) { if (demo.id === this.demoId) { demo.initialize(); demo.registerOptions(this.resetMenu()); this.loadedDemos.add(demo); load.demo = demo; this.dispatchEvent(load); } } loadDemo(id) { const nextDemo = this.demos.get(id); const currentDemo = this.currentDemo; const renderer = this.renderer; window.location.hash = nextDemo.id; if (currentDemo !== null) { currentDemo.dispose(); currentDemo.reset(); } this.menu.domElement.style.display = "none"; change.previousDemo = currentDemo; change.demo = nextDemo; this.currentDemo = nextDemo; this.demoId = id; this.dispatchEvent(change); this.loadedDemos.delete(nextDemo); renderer.clear(); nextDemo.load().then(() => this.startDemo(nextDemo)).catch((e) => console.error(e)); } getCurrentDemo() { return this.currentDemo; } addDemo(demo) { const hash = window.location.hash.slice(1); const currentDemo = this.currentDemo; this.demos.set(demo.id, demo.setRenderer(this.renderer)); if (this.demoId === null && hash.length === 0 || demo.id === hash) { this.loadDemo(demo.id); } this.resetMenu(); if (currentDemo !== null && this.loadedDemos.has(currentDemo)) { currentDemo.registerOptions(this.menu); } return this; } removeDemo(id) { const demos = this.demos; if (demos.has(id)) { demos.delete(id); if (this.demoId === id && demos.size > 0) { const entries = Array.from(demos.entries()); const firstEntry = entries[0]; this.currentDemo = firstEntry[1]; this.loadDemo(firstEntry[0]); } else { this.demoId = null; this.currentDemo = null; this.renderer.clear(); } } return this; } setSize(width, height, updateStyle = true) { const demo = this.currentDemo; const camera = demo.getCamera(); this.renderer.setSize(width, height, updateStyle); if (demo !== null && camera !== null) { if (camera instanceof OrthographicCamera) { camera.left = width / -2; camera.right = width / 2; camera.top = height / 2; camera.bottom = height / -2; camera.updateProjectionMatrix(); } else if (camera instanceof PerspectiveCamera) { camera.aspect = width / height; camera.updateProjectionMatrix(); } } } render(timestamp) { const demo = this.currentDemo; const elapsed = (timestamp - this.timestamp) * MILLISECONDS_TO_SECONDS; this.timestamp = timestamp; if (demo !== null && this.loadedDemos.has(demo)) { demo.update(elapsed, timestamp); demo.render(elapsed, timestamp); } } }; // src/utils/CameraUtils.ts var DEG2RAD = Math.PI / 180; var RAD2DEG = 180 / Math.PI; function calculateVerticalFoV(horizontalFoV, aspect = 16 / 9) { return Math.atan(Math.tan(horizontalFoV * DEG2RAD * 0.5) / aspect) * RAD2DEG * 2; } function calculateHorizontalFoV(verticalFoV, aspect = 16 / 9) { return Math.atan(Math.tan(verticalFoV * DEG2RAD * 0.5) * aspect) * RAD2DEG * 2; } export { Demo, DemoManager, DemoManagerEvent, calculateHorizontalFoV, calculateVerticalFoV };