diff --git a/CHANGELOG.md b/CHANGELOG.md index d1c27682f04fc41930c12bd2eff2676d3b92fc2f..e58412c8838d57cc0cff4d6ec439c9072a093555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Note that since we don't clearly distinguish between a public and private interf ## [Unreleased] -- Add `HeadlessPluginContext` and `Canvas3DRenderer` to be used in Node.js +- Add `HeadlessPluginContext` and `HeadlessScreenshotHelper` to be used in Node.js - Add example `image-renderer` - Fix wrong offset when rendering text with orthographic projection - Update camera/handle helper when `devicePixelRatio` changes diff --git a/src/examples/image-renderer/index.ts b/src/examples/image-renderer/index.ts index ceed7ccc301e2a53a795901f7e79f1f1842ff6c3..4acaa96cd27581bec00a8e88d855f71b83b0e236 100644 --- a/src/examples/image-renderer/index.ts +++ b/src/examples/image-renderer/index.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Adam Midlik <midlik@gmail.com> * @@ -10,15 +10,15 @@ */ import { ArgumentParser } from 'argparse'; -import * as fs from 'fs'; +import fs from 'fs'; import path from 'path'; -import { STYLIZED_POSTPROCESSING } from '../../mol-canvas3d/renderer'; import { Download, ParseCif } from '../../mol-plugin-state/transforms/data'; import { ModelFromTrajectory, StructureComponent, StructureFromModel, TrajectoryFromMmCif } from '../../mol-plugin-state/transforms/model'; import { StructureRepresentation3D } from '../../mol-plugin-state/transforms/representation'; import { HeadlessPluginContext } from '../../mol-plugin/headless-plugin-context'; import { DefaultPluginSpec } from '../../mol-plugin/spec'; +import { STYLIZED_POSTPROCESSING } from '../../mol-plugin/util/headless-screenshot'; interface Args { diff --git a/src/mol-plugin/headless-plugin-context.ts b/src/mol-plugin/headless-plugin-context.ts index dd765ecb65d278e5d1b457dc8ae1e4457509c85f..0d547a13425f47726caf49e1697f603958cfc6a8 100644 --- a/src/mol-plugin/headless-plugin-context.ts +++ b/src/mol-plugin/headless-plugin-context.ts @@ -1,25 +1,24 @@ /** - * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Adam Midlik <midlik@gmail.com> */ -import * as fs from 'fs'; - +import fs from 'fs'; import { Canvas3D } from '../mol-canvas3d/canvas3d'; import { PostprocessingProps } from '../mol-canvas3d/passes/postprocessing'; -import { Canvas3DRenderer, ImageRendererOptions } from '../mol-canvas3d/renderer'; import { PluginContext } from './context'; import { PluginSpec } from './spec'; +import { HeadlessScreenshotHelper, HeadlessScreenshotHelperOptions } from './util/headless-screenshot'; /** PluginContext that can be used in Node.js (without DOM) */ export class HeadlessPluginContext extends PluginContext { - renderer: Canvas3DRenderer; + renderer: HeadlessScreenshotHelper; - constructor(spec: PluginSpec, canvasSize: { width: number, height: number } = { width: 640, height: 480 }, rendererOptions?: ImageRendererOptions) { + constructor(spec: PluginSpec, canvasSize: { width: number, height: number } = { width: 640, height: 480 }, rendererOptions?: HeadlessScreenshotHelperOptions) { super(spec); - this.renderer = new Canvas3DRenderer(canvasSize, undefined, rendererOptions); + this.renderer = new HeadlessScreenshotHelper(canvasSize, undefined, rendererOptions); (this.canvas3d as Canvas3D) = this.renderer.canvas3d; } diff --git a/src/mol-canvas3d/renderer.ts b/src/mol-plugin/util/headless-screenshot.ts similarity index 89% rename from src/mol-canvas3d/renderer.ts rename to src/mol-plugin/util/headless-screenshot.ts index 00bf5ed0d114ead669d4c1cae5b39a3395aafa9a..aa98ebad00b15bca25257f21eff45fb453842e05 100644 --- a/src/mol-canvas3d/renderer.ts +++ b/src/mol-plugin/util/headless-screenshot.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2019-2023 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Jesse Liang <jesse.liang@rcsb.org> @@ -8,23 +8,22 @@ * @author Adam Midlik <midlik@gmail.com> */ -import * as fs from 'fs'; +import fs from 'fs'; import path from 'path'; - import { type BufferRet as JpegBufferRet } from 'jpeg-js'; // Only import type here, the actual import is done by LazyImports import { type PNG } from 'pngjs'; // Only import type here, the actual import is done by LazyImports -import { createContext } from '../mol-gl/webgl/context'; -import { AssetManager } from '../mol-util/assets'; -import { ColorNames } from '../mol-util/color/names'; -import { PixelData } from '../mol-util/image'; -import { InputObserver } from '../mol-util/input/input-observer'; -import { LazyImports } from '../mol-util/lazy-imports'; -import { ParamDefinition } from '../mol-util/param-definition'; -import { Canvas3D, Canvas3DContext, Canvas3DProps, DefaultCanvas3DParams } from './canvas3d'; -import { ImagePass, ImageProps } from './passes/image'; -import { Passes } from './passes/passes'; -import { PostprocessingParams, PostprocessingProps } from './passes/postprocessing'; +import { Canvas3D, Canvas3DContext, Canvas3DProps, DefaultCanvas3DParams } from '../../mol-canvas3d/canvas3d'; +import { ImagePass, ImageProps } from '../../mol-canvas3d/passes/image'; +import { Passes } from '../../mol-canvas3d/passes/passes'; +import { PostprocessingParams, PostprocessingProps } from '../../mol-canvas3d/passes/postprocessing'; +import { createContext } from '../../mol-gl/webgl/context'; +import { AssetManager } from '../../mol-util/assets'; +import { ColorNames } from '../../mol-util/color/names'; +import { PixelData } from '../../mol-util/image'; +import { InputObserver } from '../../mol-util/input/input-observer'; +import { LazyImports } from '../../mol-util/lazy-imports'; +import { ParamDefinition } from '../../mol-util/param-definition'; const lazyImports = LazyImports.create('gl', 'jpeg-js', 'pngjs') as { @@ -34,7 +33,7 @@ const lazyImports = LazyImports.create('gl', 'jpeg-js', 'pngjs') as { }; -export type ImageRendererOptions = { +export type HeadlessScreenshotHelperOptions = { webgl?: WebGLContextAttributes, canvas?: Partial<Canvas3DProps>, imagePass?: Partial<ImageProps>, @@ -48,11 +47,11 @@ export type RawImageData = { /** To render Canvas3D when running in Node.js (without DOM) */ -export class Canvas3DRenderer { +export class HeadlessScreenshotHelper { readonly canvas3d: Canvas3D; readonly imagePass: ImagePass; - constructor(readonly canvasSize: { width: number, height: number }, canvas3d?: Canvas3D, options?: ImageRendererOptions) { + constructor(readonly canvasSize: { width: number, height: number }, canvas3d?: Canvas3D, options?: HeadlessScreenshotHelperOptions) { if (canvas3d) { this.canvas3d = canvas3d; } else { diff --git a/src/mol-util/assets.ts b/src/mol-util/assets.ts index 7a14df662a9d8741123f398bc0d925bf5dd17500..9c1f8cb71921bc675ba2e73914c3716e2ac65c05 100644 --- a/src/mol-util/assets.ts +++ b/src/mol-util/assets.ts @@ -9,7 +9,7 @@ import { UUID } from './uuid'; import { iterableToArray } from '../mol-data/util'; import { ajaxGet, DataType, DataResponse, readFromFile } from './data-source'; import { Task } from '../mol-task'; -import { File_ as File } from './nodejs-browser-io'; +import { File_ as File } from './nodejs-shims'; export { AssetManager, Asset }; diff --git a/src/mol-util/data-source.ts b/src/mol-util/data-source.ts index 37f6cb983ee2907aa180d333d3a268232662071a..753fbc36e11a9d7b1cc23f514c0f65c3347e2941 100644 --- a/src/mol-util/data-source.ts +++ b/src/mol-util/data-source.ts @@ -1,19 +1,24 @@ /** - * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> + * @author Adam Midlik <midlik@gmail.com> * * Adapted from LiteMol */ -import * as fs from 'fs'; - -import { Task, RuntimeContext } from '../mol-task'; -import { unzip, ungzip } from './zip/zip'; import { utf8Read } from '../mol-io/common/utf8'; -import { AssetManager, Asset } from './assets'; -import { RUNNING_IN_NODEJS, File_ as File, XMLHttpRequest_ as XMLHttpRequest } from './nodejs-browser-io'; +import { RuntimeContext, Task } from '../mol-task'; +import { Asset, AssetManager } from './assets'; +import { LazyImports } from './lazy-imports'; +import { File_ as File, RUNNING_IN_NODEJS, XMLHttpRequest_ as XMLHttpRequest } from './nodejs-shims'; +import { ungzip, unzip } from './zip/zip'; + + +const lazyImports = LazyImports.create('fs') as { + 'fs': typeof import ('fs'), +}; export enum DataCompressionMethod { @@ -306,7 +311,7 @@ function ajaxGetInternal_file_NodeJS<T extends DataType>(title: string | undefin if (!RUNNING_IN_NODEJS) throw new Error('This function should only be used when running in Node.js'); if (!url.startsWith('file://')) throw new Error('This function is only for URLs with protocol file://'); const filename = url.substring('file://'.length); - const data = fs.readFileSync(filename); + const data = lazyImports.fs.readFileSync(filename); const file = new File([data], 'raw-data'); return readFromFile(file, type); } diff --git a/src/mol-util/lazy-imports.ts b/src/mol-util/lazy-imports.ts index 61e2619e3bb945bb40867db22055406825241fb1..774e9a4d110f2761a58928b69f24353f11a4c2d4 100644 --- a/src/mol-util/lazy-imports.ts +++ b/src/mol-util/lazy-imports.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2019-2023 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Adam Midlik <midlik@gmail.com> * diff --git a/src/mol-util/nodejs-browser-io.ts b/src/mol-util/nodejs-shims.ts similarity index 87% rename from src/mol-util/nodejs-browser-io.ts rename to src/mol-util/nodejs-shims.ts index 973113efa5964877b7429437f04ff4706bf691d8..fd4304860f5fe386656e28a6f01865dbe54e91e9 100644 --- a/src/mol-util/nodejs-browser-io.ts +++ b/src/mol-util/nodejs-shims.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Adam Midlik <midlik@gmail.com> * @@ -8,8 +8,8 @@ */ -/** Determines whether the current code is running in Node.js or in a browser */ -export const RUNNING_IN_NODEJS = typeof document === 'undefined'; +/** Determines whether the current code is running in Node.js */ +export const RUNNING_IN_NODEJS = typeof process !== 'undefined' && process.versions != null && process.versions.node != null; /** Like `XMLHttpRequest` but works also in Node.js */ export const XMLHttpRequest_ = getXMLHttpRequest();