multiplane 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -254,6 +254,8 @@ npx multiplane stills shot.html --every 0.5
254
254
 
255
255
  ## 3D layer
256
256
 
257
+ The desktop app and its bundled command already include three.js (pinned at 0.180.0) for the 3D layer; nothing else to install. With the npm package, three.js is an optional dependency that projects using the 3D layer install themselves:
258
+
257
259
  ```sh
258
260
  npm install three@0.180.0
259
261
  ```
package/README.md CHANGED
@@ -254,6 +254,8 @@ npx multiplane stills shot.html --every 0.5
254
254
 
255
255
  ## 三维层
256
256
 
257
+ 用桌面软件或它自带的命令行渲染时,三维层要用的 three.js(固定 0.180.0)已经带在软件里,不用另装。通过 npm 使用时,three.js 是可选依赖,用三维层的项目自己装:
258
+
257
259
  ```sh
258
260
  npm install three@0.180.0
259
261
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multiplane",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -117,7 +117,7 @@ Use `/* multiplane-disable-next-line css_animation */` in CSS and `<!-- multipla
117
117
 
118
118
  ## 3D layer (optional)
119
119
 
120
- Use `multiplane/three` when you need 3D cards or depth of field. Install `three@0.180.0` in the project (`npm install three@0.180.0`).
120
+ Use `multiplane/three` when you need 3D cards or depth of field. When the renderer is the desktop app's bundled command, three.js 0.180.0 is already included. With the npm package, install `three@0.180.0` in the project (`npm install three@0.180.0`). `multiplane doctor` reports whether three.js is available, its version and where it comes from.
121
121
 
122
122
  ```html
123
123
  <script type="importmap">{"imports":{
package/src/doctor.mjs CHANGED
@@ -3,6 +3,7 @@ import { runCommand } from './events.mjs';
3
3
  import { launchBrowser, environment, warnGpuFallback } from './environment.mjs';
4
4
  import { inspectFFmpeg, ffmpegOutput } from './ffmpeg.mjs';
5
5
  import { MultiplaneError } from './errors.mjs';
6
+ import { threeCheck } from './three-package.mjs';
6
7
 
7
8
  export function benchmarkCheck(record, machine) {
8
9
  const current = validBenchmark(record, machine);
@@ -48,8 +49,7 @@ export const doctor = (options = {}) => runCommand('doctor', null, options, asyn
48
49
  for (const name of ['libvpx-vp9', 'prores_ks']) checks.push({ name, ok: false, detail: `${name} is optional; encoder availability could not be inspected.` });
49
50
  }
50
51
  if (info) events.emit('environment', { ...info, ffmpeg: ffmpeg ?? null });
51
- try { await import('three'); checks.push({ name: 'three', ok: true, detail: 'Optional three.js is available.' }); }
52
- catch { checks.push({ name: 'three', ok: false, detail: 'Optional three.js is not installed.' }); }
52
+ checks.push(await threeCheck());
53
53
  if (failure && checks.some(c => ['ffmpeg', 'libx264'].includes(c.name) && !c.ok)) failure.hint = (failure.hint ? failure.hint + ' ' : '') + 'Run multiplane config set ffmpeg <path> to save an FFmpeg executable.';
54
54
  if (failure) { failure.result = { data: { checks, config: events.config } }; throw failure; }
55
55
  return { checks, config: events.config };
package/src/server.mjs CHANGED
@@ -5,6 +5,7 @@ import { stat, readdir } from 'node:fs/promises';
5
5
  import path from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { MultiplaneError, invalidOption } from './errors.mjs';
8
+ import { resolveThree } from './three-package.mjs';
8
9
 
9
10
  export const root = process.cwd();
10
11
  const packageRoot = fileURLToPath(new URL('../', import.meta.url));
@@ -52,7 +53,7 @@ export async function startServer(port = 0, root = process.cwd()) {
52
53
  if (pathname.startsWith('/multiplane/runtime/')) { resourceRoot = path.join(packageRoot, 'src/runtime'); resourcePath = pathname.slice('/multiplane/runtime'.length); }
53
54
  else if (pathname === '/multiplane/three.js') { resourceRoot = path.join(packageRoot, 'src/three'); resourcePath = '/index.js'; }
54
55
  else if (pathname.startsWith('/multiplane/vendor/three/')) {
55
- resourceRoot = path.dirname(path.dirname(fileURLToPath(import.meta.resolve('three'))));
56
+ resourceRoot = (await resolveThree()).root;
56
57
  resourcePath = pathname.slice('/multiplane/vendor/three'.length);
57
58
  if (!/^\/(build|examples\/jsm)\/.*\.js$/.test(resourcePath)) { res.writeHead(403); return res.end(); }
58
59
  } else { res.writeHead(404); return res.end(); }
@@ -0,0 +1,26 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ // Desktop bundles keep the tested subset separate from optional npm peers.
6
+ export async function resolveThree() {
7
+ let root = fileURLToPath(new URL('../vendor/three/', import.meta.url));
8
+ let source = 'bundled';
9
+ let pkg;
10
+ try { pkg = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8')); }
11
+ catch (error) {
12
+ if (error.code !== 'ENOENT') throw error;
13
+ root = path.dirname(path.dirname(fileURLToPath(import.meta.resolve('three'))));
14
+ pkg = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
15
+ source = 'project';
16
+ }
17
+ return { root, version: pkg.version, source };
18
+ }
19
+
20
+ export async function threeCheck() {
21
+ try {
22
+ const { root, version, source } = await resolveThree();
23
+ await readFile(path.join(root, 'build/three.module.js'));
24
+ return { name: 'three', ok: true, detail: `three.js ${version} is available (${source === 'bundled' ? 'bundled with software' : 'installed by project'}).` };
25
+ } catch { return { name: 'three', ok: false, detail: 'Optional three.js is not installed.' }; }
26
+ }