@volter/editor-threejs 0.5.210 → 0.5.212

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.
Files changed (133) hide show
  1. package/NOTICE +7 -2
  2. package/README.md +8 -13
  3. package/contributions/animation-mixers.service.ts +2 -4
  4. package/contributions/animation-timeline.utility.tsx +1 -2
  5. package/contributions/three.page.ts +50 -0
  6. package/dist-node/serving.mjs +84 -3
  7. package/dist-node/shared-three.mjs +145 -0
  8. package/package.json +296 -16
  9. package/serving/animation-stamp.ts +1 -1
  10. package/serving/index.ts +22 -5
  11. package/serving/model-import-conversion.ts +6 -3
  12. package/serving/shared-three.ts +176 -0
  13. package/src/adapter/constraint.ts +1 -18
  14. package/src/adapter/object3d-authoring-subject.ts +1 -12
  15. package/src/adapter/reflection-probe.ts +1 -9
  16. package/src/adapter/three-contract.ts +6 -60
  17. package/src/animation/live-mixers.ts +0 -4
  18. package/src/api.ts +7 -0
  19. package/src/asset-loaders.ts +2 -178
  20. package/src/capture/photograph-sampling.ts +333 -0
  21. package/src/capture/scene.ts +1 -1
  22. package/src/ecs/object-marks.ts +6 -14
  23. package/src/ecs/user-data.ts +3 -138
  24. package/src/kit/animation/three-clips-subject.ts +19 -42
  25. package/src/kit/asset-compare-core.ts +161 -0
  26. package/src/kit/asset-compare.ts +8 -27
  27. package/src/kit/asset-preview-command.ts +14 -19
  28. package/src/kit/asset-preview-framing.ts +8 -67
  29. package/src/kit/asset-preview.ts +109 -342
  30. package/src/kit/asset-workflow/model-inspection.ts +11 -154
  31. package/src/kit/asset-workflow/preview-resource-lifetime.ts +25 -0
  32. package/src/kit/authoring/component-instance-root.ts +3 -39
  33. package/src/kit/authoring/live-object-transform.ts +1 -30
  34. package/src/kit/authoring/object3d-document-session-registry.ts +7 -15
  35. package/src/kit/authoring/object3d-document-session.ts +471 -208
  36. package/src/kit/authoring/shell-viewport-policy.ts +18 -24
  37. package/src/kit/authoring/source-object3d-authoring-adapter.ts +6 -48
  38. package/src/kit/authoring/three-projection-core.ts +11 -40
  39. package/src/kit/authoring/viewport-pick-context.ts +5 -12
  40. package/src/kit/authoring/viewport-raycast.ts +15 -93
  41. package/src/kit/authoring/world-hidden-viewport.ts +8 -61
  42. package/src/kit/capture-camera-pose.ts +68 -0
  43. package/src/kit/collaboration-presence.ts +41 -0
  44. package/src/kit/components/CameraInfo.tsx +4 -6
  45. package/src/kit/components/InspectorObjectPreview.tsx +3 -30
  46. package/src/kit/components/Object3DDocumentToolbar.css +75 -0
  47. package/src/kit/components/Object3DDocumentToolbar.tsx +18 -84
  48. package/src/kit/components/Object3DDocumentViewport.tsx +5 -8
  49. package/src/kit/components/StageHost.css +40 -0
  50. package/src/kit/components/StageHost.tsx +181 -404
  51. package/src/kit/components/StageOverlays.tsx +1 -2
  52. package/src/kit/components/StatsOverlay.tsx +5 -17
  53. package/src/kit/components/ViewportFurniture.tsx +27 -154
  54. package/src/kit/components/ViewportOverlay.tsx +13 -17
  55. package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
  56. package/src/kit/components/ViewportShadingMenu.tsx +2 -42
  57. package/src/kit/components/ViewportViewMenu.tsx +7 -18
  58. package/src/kit/components/asset-viewers/EntityModelDocument.tsx +4 -13
  59. package/src/kit/components/asset-viewers/EnvironmentAssetDocument.tsx +5 -5
  60. package/src/kit/components/asset-viewers/LiveModuleDocument.tsx +24 -102
  61. package/src/kit/components/asset-viewers/LutAssetDocument.tsx +6 -6
  62. package/src/kit/components/asset-viewers/Object3DPreview.tsx +10 -45
  63. package/src/kit/components/asset-viewers/QuarksAssetDocument.tsx +2 -2
  64. package/src/kit/components/asset-viewers/ShaderAssetDocument.tsx +11 -10
  65. package/src/kit/components/asset-viewers/shader-source.ts +144 -0
  66. package/src/kit/components/asset-viewers/three-asset-viewers.tsx +2 -14
  67. package/src/kit/components/object3d-contribution-surfaces.tsx +1 -1
  68. package/src/kit/components/stage-keyboard.tsx +6 -12
  69. package/src/kit/components/stage-overlay-set.tsx +11 -20
  70. package/src/kit/components/stage-presence-markers.ts +9 -32
  71. package/src/kit/components/stage-transform-chrome.ts +4 -4
  72. package/src/kit/components/stage-transform-tools.tsx +7 -14
  73. package/src/kit/components/standard-viewport-dressing.ts +47 -167
  74. package/src/kit/components/world-root-binding.ts +2 -7
  75. package/src/kit/constraint-helper.ts +1 -1
  76. package/src/kit/document-renderer-session.ts +114 -0
  77. package/src/kit/editor-presentation-activity.ts +58 -0
  78. package/src/kit/editor-shell-store.ts +31 -403
  79. package/src/kit/editor-viewport.ts +476 -1762
  80. package/src/kit/entity-lod.ts +3 -16
  81. package/src/kit/entity-object.ts +1 -39
  82. package/src/kit/hierarchy-mark-reader.ts +13 -30
  83. package/src/kit/instanced-presentation.ts +1 -47
  84. package/src/kit/live-gesture-lock.ts +35 -0
  85. package/src/kit/live-module-source.ts +12 -52
  86. package/src/kit/model-thumbnail.ts +7 -35
  87. package/src/kit/play-camera-flight.ts +7 -16
  88. package/src/kit/projection/three.ts +13 -366
  89. package/src/kit/retained-document-states.ts +91 -0
  90. package/src/kit/scene-document-viewport.ts +3 -3
  91. package/src/kit/scene-framing.ts +11 -152
  92. package/src/kit/scene-view-fog.ts +2 -47
  93. package/src/kit/spatial-handle-visuals.ts +19 -28
  94. package/src/kit/stories/three-story-model.ts +5 -33
  95. package/src/kit/three-canvas-render.ts +3 -4
  96. package/src/kit/three-hierarchy-row-media.ts +3 -11
  97. package/src/kit/three-inspection-media.ts +6 -6
  98. package/src/kit/three-integration.ts +18 -18
  99. package/src/kit/three-state.ts +2 -19
  100. package/src/kit/three-viewport/camera-fit.ts +2 -6
  101. package/src/kit/three-viewport/selection-brackets.ts +5 -20
  102. package/src/kit/three-viewport/selection-outline.ts +4 -56
  103. package/src/kit/three-viewport/skeleton-helper.ts +1 -32
  104. package/src/kit/three-viewport/source-color.ts +1 -33
  105. package/src/kit/three-viewport/studio-environment.ts +4 -55
  106. package/src/kit/three-viewport-presentation.ts +23 -0
  107. package/src/kit/transport-strip.tsx +147 -0
  108. package/src/kit/viewport-actions.ts +8 -50
  109. package/src/kit/viewport-authoring-policy.ts +5 -52
  110. package/src/kit/viewport-commands.ts +28 -57
  111. package/src/kit/viewport-hotkeys.ts +29 -31
  112. package/src/kit/viewport-status-facet.ts +4 -5
  113. package/src/kit/viewport-surface-status.tsx +44 -0
  114. package/src/loader.ts +8 -71
  115. package/src/object3d-contributions.ts +18 -34
  116. package/src/viewport/clip-planes.ts +4 -32
  117. package/src/viewport/content-bounds.ts +13 -142
  118. package/src/viewport/editor-layers.ts +4 -26
  119. package/src/viewport/environment.ts +1 -1
  120. package/src/viewport/preview-renderer.ts +7 -45
  121. package/src/viewport/renderer-ownership.ts +14 -62
  122. package/src/viewport-api.ts +14 -33
  123. package/src/viewport-door.ts +16 -86
  124. package/contributions/three-integration.service.ts +0 -13
  125. package/src/adapter/hierarchy-marks.ts +0 -156
  126. package/src/adapter/ingest/scene-capture.ts +0 -843
  127. package/src/adapter/ingest/structural-ids.ts +0 -139
  128. package/src/adapter/ingest/visible-capture-window.ts +0 -302
  129. package/src/adapter/renderer-config.ts +0 -115
  130. package/src/asset-parse-error.ts +0 -29
  131. package/src/host-hierarchy-objects.ts +0 -31
  132. package/src/kit/authoring/design-time-settle.ts +0 -343
  133. package/src/kit/camera-authoring.ts +0 -175
package/NOTICE CHANGED
@@ -10,5 +10,10 @@ with src/asset-loaders.ts, src/asset-parse-error.ts and src/loader.ts, were
10
10
  imported from the Apache-2.0 @volter/threejs-runtime package. They retain that
11
11
  license; LICENSE-APACHE contains its text.
12
12
 
13
- Source revisions and original file hashes are recorded in the repository's
14
- provenance/blender-integration.json and provenance/editor-host.json.
13
+ Original AGPL source revision: cf9cb8e22dd7ae5709ed0dd8a46dd6f16d1e4945.
14
+ The Apache-2.0 runtime modules were transferred at revision 09c2749ce.
15
+
16
+ Modules moved under src/kit/ from @volter/sdk's src/kit/ because only this package
17
+ imports them (docs/adr/sdk-plugin-api.md, decisions 1 and 4) are Volter AI, Inc.'s
18
+ own work and are AGPL-3.0-only here, as editor source. The @volter/sdk releases
19
+ that carried them remain Apache-2.0.
package/README.md CHANGED
@@ -1,16 +1,11 @@
1
- # Three.js editor utilities
1
+ # Cyclotron three.js integration
2
2
 
3
- Shared bounds, layers, clipping, renderer ownership, preview environment and
4
- detached scene capture used by Volter Editor's modeling integration.
3
+ The assembled three.js viewport, scene presentation, object authoring, animation
4
+ inspection, asset loading and capture used by Cyclotron and its Blender integration.
5
5
 
6
- This package does not yet own the interactive viewport. The current Three-aware
7
- editor core retains that implementation; full extraction remains deferred.
8
- No game-runtime, DOM authoring, physics or gameplay packages are dependencies.
6
+ The integration reaches the editor host through `@volter/sdk`. Structural object
7
+ marks and asset utilities keep their own small module boundaries, so a consumer
8
+ can load them independently of the viewport.
9
9
 
10
- Structural object marks retain their existing keys and behavior. Their readers
11
- are included here because bounds and editor-layer filtering need them; importing
12
- these small modules must not pull in a gameplay runtime.
13
-
14
- Run `npm run typecheck -w @volter/editor-threejs` through the active World.
15
- See NOTICE for the per-file license distinction. This package remains private
16
- while the editor migration and complete distribution review are unfinished.
10
+ Run `npm run typecheck -w @volter/editor-threejs` from the repository root.
11
+ See NOTICE for the per-file license distinction.
@@ -1,8 +1,6 @@
1
1
  /**
2
- * The animation stamp's status facet (`@volter/sdk/services`, a `workspace.service`
3
- * contribution): the editor's `status` command reports the mixers the running world's own code made, with the
4
- * clips it has played through each and the objects each animates, so "the timeline found
5
- * nothing" is answerable from the session.
2
+ * Report live animation mixers, their played clips and animated objects through a workspace service
3
+ * status facet.
6
4
  */
7
5
  import { editorHost } from '@volter/sdk/host';
8
6
  import { liveMixers } from '../src/animation/live-mixers';
@@ -6,12 +6,11 @@
6
6
  * its Scene view. While Play drives time the strip goes read-only and says why.
7
7
  */
8
8
  import { editorHost } from '@volter/sdk/host';
9
- import { TransportStrip } from '@volter/sdk/kit/transport-strip';
9
+ import { TransportStrip } from '../src/kit/transport-strip';
10
10
  import { Text } from '@volter/sdk/widgets';
11
11
  import { useCallback, useSyncExternalStore } from 'react';
12
12
 
13
13
  export const point = 'workspace.utility';
14
- export const title = 'Animation';
15
14
 
16
15
  export default function AnimationTimeline() {
17
16
  const { documents, transport } = editorHost();
@@ -0,0 +1,50 @@
1
+ /**
2
+ * EDITOR-THREEJS'S PAGE HALF (`contributes.volter.page`, `docs/adr/plugin-apis.md`): it installs the
3
+ * Three integration (`../src/kit/three-integration.ts`) and registers the Three viewport's relay verbs as
4
+ * the Code-OSS commands `volter.<verb>` its package.json declares, with their budgets
5
+ * (`../src/kit/viewport-commands.ts`). Its API is the shared viewport for a document that draws its own content in it:
6
+ * the viewport, each mounted stage (its rig, renderer included, and its frame), a document's display transform, its
7
+ * framing and its World.
8
+ *
9
+ * It activates on its first event: a viewport verb, the Animation panel's first showing, an Asset Lab
10
+ * route with no viewer (`onAssetViewer:`), or a JSON document opening (`onAssetViewer:json`), whose three.quarks
11
+ * particle systems its recognizer claims; and before editor-blender, which names it in `extensionDependencies`
12
+ * because a model document draws through the surfaces and stages this integration installs. A viewport that editor-blender or editor-ui mounts as a library
13
+ * ensures the integration itself before it mounts, whether or not this page half has activated.
14
+ */
15
+ import { registerVerbCommands } from '@volter/sdk/commands';
16
+ import type { PluginContext } from '@volter/sdk/plugins';
17
+ import type * as THREE from 'three';
18
+ import { object3DDocumentSession } from '../src/kit/authoring/object3d-document-session-registry';
19
+ import { Object3DDocumentViewport } from '../src/kit/components/Object3DDocumentViewport';
20
+ import { ensureThreeIntegration } from '../src/kit/three-integration';
21
+ import { viewportVerbs } from '../src/kit/viewport-commands';
22
+ import type { DocumentDisplayTransform } from '../src/render/document-display-transform';
23
+ import { DocumentScene } from '../src/render/document-scene';
24
+ import { onViewportStages, viewportStages } from '../src/viewport-door';
25
+
26
+ export function activate(context: PluginContext) {
27
+ context.subscriptions.push({ dispose: ensureThreeIntegration() });
28
+ registerVerbCommands(context, viewportVerbs);
29
+ return {
30
+ /** The shared viewport (orbit, pick, framing, overlays), drawing the root a document's `build` answers. */
31
+ Object3DDocumentViewport,
32
+ /** The stage a document has mounted, while it has one. */
33
+ stage: (documentId: string) => viewportStages().find((one) => one.documentId === documentId) ?? null,
34
+ /** Fires whenever a stage mounts or unmounts; the return unsubscribes. */
35
+ onStages: onViewportStages,
36
+ /** The scene-linear-to-display transform a document's stage applies to every frame it draws (null: the stage's
37
+ * own); false where the document has no stage session. */
38
+ setDisplayTransform(documentId: string, transform: DocumentDisplayTransform | null): boolean {
39
+ const session = object3DDocumentSession(documentId);
40
+ session?.setDisplayTransform(transform);
41
+ return session !== null;
42
+ },
43
+ /** Frame everything the document's stage draws, as the viewport's Frame All does; false where the document has
44
+ * no stage session or nothing to frame. */
45
+ frameAll: (documentId: string): boolean => object3DDocumentSession(documentId)?.frame(1, 'all') ?? false,
46
+ /** A document's World: the scene its `build` root stands in, whose background, environment and fog the stage draws
47
+ * by (it mirrors them into the scene it renders); null while the root stands in no stage. */
48
+ documentWorld: (root: THREE.Object3D): THREE.Scene | null => (root.parent instanceof DocumentScene ? root.parent : null),
49
+ };
50
+ }
@@ -285,7 +285,9 @@ async function parseSourceModel(primaryPath, format, bytes) {
285
285
  return loader.parse(new TextDecoder().decode(bytes));
286
286
  }
287
287
  case "dae": {
288
- return new ColladaLoader().parse(new TextDecoder().decode(bytes), resourcePath).scene;
288
+ const collada = new ColladaLoader().parse(new TextDecoder().decode(bytes), resourcePath);
289
+ if (!collada) throw new Error(`${primaryPath} is not a COLLADA document`);
290
+ return collada.scene;
289
291
  }
290
292
  case "stl": {
291
293
  const geometry = new STLLoader().parse(bytes.buffer);
@@ -395,11 +397,90 @@ function disposeObject(root) {
395
397
  });
396
398
  }
397
399
 
400
+ // serving/shared-three.ts
401
+ import { readFileSync } from "node:fs";
402
+ import path from "node:path";
403
+
404
+ // ../sdk/src/shared-doorway.ts
405
+ var SHARED_DOORWAY_PREFIX = "\0volter-shared:";
406
+ function sharedDoorwayId(specifier) {
407
+ return `${SHARED_DOORWAY_PREFIX}${specifier}`;
408
+ }
409
+
410
+ // serving/shared-three.ts
411
+ var SHARED_THREE_SPECIFIER = "three";
412
+ var SHARED_THREE_MANIFEST_FILE = "volter-shared-three.json";
413
+ function readSharedThreeManifest(distPath) {
414
+ const manifestPath = path.join(distPath, SHARED_THREE_MANIFEST_FILE);
415
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
416
+ if (typeof manifest.file !== "string" || !manifest.file || typeof manifest.coreFile !== "string" || !manifest.coreFile)
417
+ throw new Error(`${manifestPath} must name the shared three.js and core chunks. Rebuild the editor.`);
418
+ return { file: manifest.file, coreFile: manifest.coreFile };
419
+ }
420
+ function sharedThreeUrl(file) {
421
+ return `/${file}`;
422
+ }
423
+ var SHARED_THREE_DOORWAY = sharedDoorwayId(SHARED_THREE_SPECIFIER);
424
+ var SHARED_THREE_CORE_DOORWAY = sharedDoorwayId("three/build/three.core.js");
425
+ function sharedThreePlugin(url, coreUrl) {
426
+ return {
427
+ // Vite includes this plugin name in the dependency cache version.
428
+ name: "volter-shared:three",
429
+ enforce: "pre",
430
+ // `three` is the shell's here, never prebundled: excluding it externalizes it out of every
431
+ // prebundled chunk (Fiber's own `import 'three'` included), so those imports resolve at serve
432
+ // time through this plugin. A specifier cannot be both included and excluded.
433
+ config(config) {
434
+ const optimizeDeps = config.optimizeDeps ??= {};
435
+ optimizeDeps.include = (optimizeDeps.include ?? []).filter((specifier) => specifier !== SHARED_THREE_SPECIFIER);
436
+ optimizeDeps.exclude = [...optimizeDeps.exclude ?? [], SHARED_THREE_SPECIFIER];
437
+ },
438
+ load(id) {
439
+ if (id === SHARED_THREE_CORE_DOORWAY) return `export * from ${JSON.stringify(coreUrl)};
440
+ `;
441
+ return id === SHARED_THREE_DOORWAY ? `export * from ${JSON.stringify(SHARED_THREE_SPECIFIER)};
442
+ export { default } from ${JSON.stringify(SHARED_THREE_SPECIFIER)};
443
+ ` : void 0;
444
+ },
445
+ resolveId(source, importer, options) {
446
+ if (importer === SHARED_THREE_CORE_DOORWAY && source === coreUrl) return coreUrl;
447
+ const cleanSource = source.split("?")[0].replaceAll("\\", "/");
448
+ const cleanImporter = (importer ?? "").split("?")[0].replaceAll("\\", "/");
449
+ const core = /(?:^|\/)three\/build\/three\.core\.js$/.test(cleanSource) || cleanSource === "./three.core.js" && /\/three\/build\/three\.[^/]+\.js$/.test(cleanImporter);
450
+ if (source !== SHARED_THREE_SPECIFIER && !core) return void 0;
451
+ if (options?.scan) return void 0;
452
+ if (core) return SHARED_THREE_CORE_DOORWAY;
453
+ return importer === SHARED_THREE_DOORWAY ? url : SHARED_THREE_DOORWAY;
454
+ }
455
+ };
456
+ }
457
+ function projectThreeDedupePlugin() {
458
+ return {
459
+ name: "volter-three-dedupe",
460
+ config: () => ({ resolve: { dedupe: [SHARED_THREE_SPECIFIER, "@react-three/fiber", "its-fine"] } })
461
+ };
462
+ }
463
+ function sharedThreeServingPlugins(shellOutputDir) {
464
+ const dedupe = projectThreeDedupePlugin();
465
+ if (shellOutputDir === null) return [dedupe];
466
+ const manifest = readSharedThreeManifest(shellOutputDir);
467
+ return [dedupe, sharedThreePlugin(sharedThreeUrl(manifest.file), sharedThreeUrl(manifest.coreFile))];
468
+ }
469
+
398
470
  // serving/index.ts
399
471
  var servingPlugins = (services) => {
400
472
  services.registerModelConverter(threeModelConverter);
401
- return [animationStampPlugin(services)];
473
+ return [...sharedThreeServingPlugins(services.shellOutputDir), animationStampPlugin(services)];
402
474
  };
475
+ var substrates = [
476
+ {
477
+ substrate: "three",
478
+ surface: "stage",
479
+ dialects: ["r3f"],
480
+ default: { dialect: "r3f", anchors: ["source-prop", "source-structure", "construction-literal"] }
481
+ }
482
+ ];
403
483
  export {
404
- servingPlugins
484
+ servingPlugins,
485
+ substrates
405
486
  };
@@ -0,0 +1,145 @@
1
+ // serving/shared-three.ts
2
+ import { readFileSync } from "node:fs";
3
+ import { createRequire as createRequire2 } from "node:module";
4
+ import path2 from "node:path";
5
+
6
+ // ../sdk/src/shared-doorway.ts
7
+ var SHARED_DOORWAY_PREFIX = "\0volter-shared:";
8
+ function sharedDoorwayId(specifier) {
9
+ return `${SHARED_DOORWAY_PREFIX}${specifier}`;
10
+ }
11
+
12
+ // ../sdk/src/shared-entry-module.ts
13
+ import { createRequire } from "node:module";
14
+ import path from "node:path";
15
+ var VALID_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
16
+ function sharedEntryModule(specifier, exportNames) {
17
+ const named = exportNames.filter((name) => VALID_IDENTIFIER.test(name)).map((name) => `export const ${name} = __m.${name};`);
18
+ return [
19
+ `import * as __ns from ${JSON.stringify(specifier)};`,
20
+ // Bracketed on purpose: `__ns.default` makes rollup warn that the ES-module
21
+ // shape (the jsx-dev-runtime shim) has no `default` export, which is the
22
+ // case this line exists to handle.
23
+ "const __m = __ns['default'] ?? __ns;",
24
+ "export default __m;",
25
+ ...named,
26
+ ""
27
+ ].join("\n");
28
+ }
29
+ function installedExportNames(fromDir, specifier) {
30
+ const require_ = createRequire(path.join(fromDir, "package.json"));
31
+ const loaded = require_(specifier);
32
+ return Object.keys(loaded).filter((name) => name !== "default");
33
+ }
34
+
35
+ // serving/shared-three.ts
36
+ var SHARED_THREE_SPECIFIER = "three";
37
+ var SHARED_THREE_ENTRY_NAME = "volter-shared-three";
38
+ var SHARED_THREE_MANIFEST_FILE = "volter-shared-three.json";
39
+ var VIRTUAL_PREFIX = "\0volter-shared-three:";
40
+ function sharedThreeBuildPlugin(fromDir) {
41
+ let referenceId;
42
+ let coreReferenceId;
43
+ return {
44
+ name: "volter-shared-three-build",
45
+ apply: "build",
46
+ buildStart() {
47
+ const require_ = createRequire2(path2.join(fromDir, "package.json"));
48
+ coreReferenceId = this.emitFile({
49
+ type: "chunk",
50
+ id: path2.join(path2.dirname(require_.resolve("three")), "three.core.js"),
51
+ name: "volter-shared-three-core",
52
+ preserveSignature: "strict"
53
+ });
54
+ referenceId = this.emitFile({
55
+ type: "chunk",
56
+ id: `${VIRTUAL_PREFIX}${SHARED_THREE_SPECIFIER}`,
57
+ name: SHARED_THREE_ENTRY_NAME,
58
+ // Same reason as the shared-React entries: Vite's app build sets
59
+ // `preserveEntrySignatures: false`, which would mangle the entry's
60
+ // export names away — `strict` keeps `Mesh` spelled `Mesh`.
61
+ preserveSignature: "strict"
62
+ });
63
+ },
64
+ resolveId(id) {
65
+ return id.startsWith(VIRTUAL_PREFIX) ? id : void 0;
66
+ },
67
+ load(id) {
68
+ if (!id.startsWith(VIRTUAL_PREFIX)) return void 0;
69
+ const specifier = id.slice(VIRTUAL_PREFIX.length);
70
+ return sharedEntryModule(specifier, installedExportNames(fromDir, specifier));
71
+ },
72
+ generateBundle() {
73
+ this.emitFile({
74
+ type: "asset",
75
+ fileName: SHARED_THREE_MANIFEST_FILE,
76
+ source: `${JSON.stringify(
77
+ { file: this.getFileName(referenceId), coreFile: this.getFileName(coreReferenceId) },
78
+ null,
79
+ 2
80
+ )}
81
+ `
82
+ });
83
+ }
84
+ };
85
+ }
86
+ function readSharedThreeManifest(distPath) {
87
+ const manifestPath = path2.join(distPath, SHARED_THREE_MANIFEST_FILE);
88
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
89
+ if (typeof manifest.file !== "string" || !manifest.file || typeof manifest.coreFile !== "string" || !manifest.coreFile)
90
+ throw new Error(`${manifestPath} must name the shared three.js and core chunks. Rebuild the editor.`);
91
+ return { file: manifest.file, coreFile: manifest.coreFile };
92
+ }
93
+ function sharedThreeUrl(file) {
94
+ return `/${file}`;
95
+ }
96
+ var SHARED_THREE_DOORWAY = sharedDoorwayId(SHARED_THREE_SPECIFIER);
97
+ var SHARED_THREE_CORE_DOORWAY = sharedDoorwayId("three/build/three.core.js");
98
+ function sharedThreePlugin(url, coreUrl) {
99
+ return {
100
+ // Vite includes this plugin name in the dependency cache version.
101
+ name: "volter-shared:three",
102
+ enforce: "pre",
103
+ // `three` is the shell's here, never prebundled: excluding it externalizes it out of every
104
+ // prebundled chunk (Fiber's own `import 'three'` included), so those imports resolve at serve
105
+ // time through this plugin. A specifier cannot be both included and excluded.
106
+ config(config) {
107
+ const optimizeDeps = config.optimizeDeps ??= {};
108
+ optimizeDeps.include = (optimizeDeps.include ?? []).filter((specifier) => specifier !== SHARED_THREE_SPECIFIER);
109
+ optimizeDeps.exclude = [...optimizeDeps.exclude ?? [], SHARED_THREE_SPECIFIER];
110
+ },
111
+ load(id) {
112
+ if (id === SHARED_THREE_CORE_DOORWAY) return `export * from ${JSON.stringify(coreUrl)};
113
+ `;
114
+ return id === SHARED_THREE_DOORWAY ? `export * from ${JSON.stringify(SHARED_THREE_SPECIFIER)};
115
+ export { default } from ${JSON.stringify(SHARED_THREE_SPECIFIER)};
116
+ ` : void 0;
117
+ },
118
+ resolveId(source, importer, options) {
119
+ if (importer === SHARED_THREE_CORE_DOORWAY && source === coreUrl) return coreUrl;
120
+ const cleanSource = source.split("?")[0].replaceAll("\\", "/");
121
+ const cleanImporter = (importer ?? "").split("?")[0].replaceAll("\\", "/");
122
+ const core = /(?:^|\/)three\/build\/three\.core\.js$/.test(cleanSource) || cleanSource === "./three.core.js" && /\/three\/build\/three\.[^/]+\.js$/.test(cleanImporter);
123
+ if (source !== SHARED_THREE_SPECIFIER && !core) return void 0;
124
+ if (options?.scan) return void 0;
125
+ if (core) return SHARED_THREE_CORE_DOORWAY;
126
+ return importer === SHARED_THREE_DOORWAY ? url : SHARED_THREE_DOORWAY;
127
+ }
128
+ };
129
+ }
130
+ function projectThreeDedupePlugin() {
131
+ return {
132
+ name: "volter-three-dedupe",
133
+ config: () => ({ resolve: { dedupe: [SHARED_THREE_SPECIFIER, "@react-three/fiber", "its-fine"] } })
134
+ };
135
+ }
136
+ function sharedThreeServingPlugins(shellOutputDir) {
137
+ const dedupe = projectThreeDedupePlugin();
138
+ if (shellOutputDir === null) return [dedupe];
139
+ const manifest = readSharedThreeManifest(shellOutputDir);
140
+ return [dedupe, sharedThreePlugin(sharedThreeUrl(manifest.file), sharedThreeUrl(manifest.coreFile))];
141
+ }
142
+ export {
143
+ sharedThreeBuildPlugin,
144
+ sharedThreeServingPlugins
145
+ };