UNPKG

threepipe

Version:

A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.

220 lines 9.62 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var CanvasSnapshotPlugin_1; import { serialize, timeout } from 'ts-browser-helpers'; import { AViewerPluginSync } from '../../viewer'; import { uiButton, uiConfig, uiFolderContainer, uiInput } from 'uiconfig.js'; import { CanvasSnapshot } from '../../utils/canvas-snapshot'; import { ProgressivePlugin } from '../pipeline/ProgressivePlugin'; import { zipSync } from 'three/examples/jsm/libs/fflate.module.js'; let CanvasSnapshotPlugin = CanvasSnapshotPlugin_1 = class CanvasSnapshotPlugin extends AViewerPluginSync { constructor() { super(); this.enabled = true; this.filename = 'snapshot'; // @uiInput('Frame Count') // @serialize() // progressiveFrames = 64 // // @uiInput('Tile Rows') // @serialize() // tileRows = 1 // // @uiInput('Tile Columns') // @serialize() // tileColumns = 1 // // @uiVector('Crop Rect (x, y, w, h)', [0, 1], 0.001) // @serialize() // rect = new Vector4(0, 0, 1, 1) this._downloading = false; /** * Only for {@link downloadSnapshot} and functions using that */ this.defaultOptions = { waitForProgressive: true, displayPixelRatio: window.devicePixelRatio, scale: 1, timeout: 0, quality: 0.9, tileRows: 1, tileColumns: 1, progressiveFrames: 64, rect: { x: 0, y: 0, width: 1, height: 1, normalized: true, assumeClientRect: false, }, }; this.downloadSnapshot = this.downloadSnapshot.bind(this); } /** * Returns a File object with screenshot of the viewer canvas * @param filename default is {@link CanvasSnapshotPlugin.filename} * @param options waitForProgressive: wait for progressive rendering to finish, default: true */ async getFile(filename, options = { waitForProgressive: true }) { return await this._getFile(filename || this.filename, { ...options, getDataUrl: false }); } /** * Returns a data url of the screenshot of the viewer canvas * @param options waitForProgressive: wait for progressive rendering to finish, default: true */ async getDataUrl(options = {}) { return await this._getFile('', { ...options, getDataUrl: true }) ?? ''; } async _getFile(filename, options = {}) { await this._viewer?.doOnce('postFrame'); const viewer = this._viewer; const canvas = this._viewer?.canvas; if (!viewer || !canvas) return undefined; viewer.scene.mainCamera.setInteractions(false, CanvasSnapshotPlugin_1.PluginType); const dpr = viewer.renderManager.renderScale; if (options.displayPixelRatio !== undefined && options.displayPixelRatio !== dpr) { viewer.renderManager.renderScale = options.displayPixelRatio; } if (options.timeout) await timeout(options.timeout); const progressive = viewer.getPlugin(ProgressivePlugin); let waitForProgressive = options.waitForProgressive ?? !!progressive; if (waitForProgressive && !progressive) { viewer.console.warn('CanvasSnapshotPlugin: ProgressivePlugin required to wait for progressive rendering'); waitForProgressive = false; } if (options.progressiveFrames && !waitForProgressive) { viewer.console.warn('CanvasSnapshotPlugin: waitForProgressive must be true to use progressiveFrames'); } const lastMaxFrames = progressive?.maxFrameCount; if (waitForProgressive && progressive) { progressive.maxFrameCount = Math.max(options.progressiveFrames ?? 64, progressive.maxFrameCount); viewer.setDirty(); await viewer.doOnce('postFrame'); while (!progressive.isConverged(true)) { await viewer.doOnce('postFrame'); // console.log(`rendering ${ 100 * this._viewer!.renderer.frameCount / progressive.maxFrameCount }%`) } } else { viewer.setDirty(); await viewer.doOnce('postFrame'); } delete options.displayPixelRatio; // const rect = options.rect // if (rect && viewer.renderManager.renderScale !== 1) { // options.rect = { // ...rect, // x: rect.x * viewer.renderManager.renderScale, // y: rect.y * viewer.renderManager.renderScale, // width: rect.width * viewer.renderManager.renderScale, // height: rect.height * viewer.renderManager.renderScale, // } // } let file; if (options.tileRows && options.tileRows > 1 || options.tileColumns && options.tileColumns > 1) { const res = await CanvasSnapshot.GetTiledFiles(canvas, filename, Math.max(1, options.tileRows || 1), Math.max(1, options.tileColumns || 1), options); if (Array.isArray(res)) { if (res.length === 1) file = res[0]; else if (res.length === 0) file = undefined; else if (!options.getDataUrl) { const zippa = {}; for (const f of res) { zippa[f.name] = new Uint8Array(await f.arrayBuffer()); } const zipped = zipSync(zippa); file = new File([zipped], filename + '.zip', { type: 'application/zip', lastModified: Date.now() }); } else { file = res; } } else { file = res; } } else { file = await CanvasSnapshot.GetFile(canvas, filename, options); } // const file = await CanvasSnapshot.GetFile(canvas, filename, options) // options.rect = rect options.displayPixelRatio = viewer.renderManager.renderScale; if (progressive && lastMaxFrames !== undefined) { progressive.maxFrameCount = lastMaxFrames; } viewer.scene.mainCamera.setInteractions(true, CanvasSnapshotPlugin_1.PluginType, false); viewer.renderManager.renderScale = dpr; return file; } // @uiButton('Download .png', {sendArgs: false}) async downloadSnapshot(filename, options = { waitForProgressive: true }) { if (!this._viewer) return; while (this._downloading) { console.warn('CanvasSnipperPlugin: Another rendering already in progress, waiting...'); await timeout(100); } this._downloading = true; // if (!options.mimeType && !filename) this.filename = this.filename.split('.').slice(0, -1).join('.') + '.png' const file = await this.getFile(filename, { ...this.defaultOptions, ...options }).catch(e => { this._viewer?.console.error('CanvasSnapshotPlugin: Error exporting file', e); return null; }); if (file) await this._viewer.exportBlob(file, file.name); this._downloading = false; } async _downloadPng() { // this.filename = this.filename.split('.').slice(0, -1).join('.') + '.png' return this.downloadSnapshot(undefined, { mimeType: 'image/png' }); } async _downloadJpeg() { // this.filename = this.filename.split('.').slice(0, -1).join('.') + '.jpeg' return this.downloadSnapshot(undefined, { mimeType: 'image/jpeg' }); } async _downloadWebp() { // this.filename = this.filename.split('.').slice(0, -1).join('.') + '.webp' return this.downloadSnapshot(undefined, { mimeType: 'image/webp' }); } }; CanvasSnapshotPlugin.PluginType = 'CanvasSnapshotPlugin'; __decorate([ uiInput('Filename'), serialize() ], CanvasSnapshotPlugin.prototype, "filename", void 0); __decorate([ uiConfig(undefined, { label: 'Options' }), serialize() ], CanvasSnapshotPlugin.prototype, "defaultOptions", void 0); __decorate([ uiButton('Download .png') ], CanvasSnapshotPlugin.prototype, "_downloadPng", null); __decorate([ uiButton('Download .jpeg') ], CanvasSnapshotPlugin.prototype, "_downloadJpeg", null); __decorate([ uiButton('Download .webp') ], CanvasSnapshotPlugin.prototype, "_downloadWebp", null); CanvasSnapshotPlugin = CanvasSnapshotPlugin_1 = __decorate([ uiFolderContainer('Image Export (Canvas Snapshot)') ], CanvasSnapshotPlugin); export { CanvasSnapshotPlugin }; /** * @deprecated - use {@link CanvasSnapshotPlugin} */ export class CanvasSnipperPlugin extends CanvasSnapshotPlugin { constructor() { super(); console.warn('CanvasSnipperPlugin is deprecated, use CanvasSnapshotPlugin'); } } CanvasSnipperPlugin.PluginType = 'CanvasSnipper'; //# sourceMappingURL=CanvasSnapshotPlugin.js.map