@volter/editor-threejs 0.5.211 → 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.
- package/NOTICE +7 -2
- package/README.md +8 -13
- package/contributions/animation-mixers.service.ts +2 -4
- package/contributions/animation-timeline.utility.tsx +1 -2
- package/contributions/three.page.ts +50 -0
- package/dist-node/serving.mjs +84 -3
- package/dist-node/shared-three.mjs +145 -0
- package/package.json +296 -16
- package/serving/animation-stamp.ts +1 -1
- package/serving/index.ts +22 -5
- package/serving/model-import-conversion.ts +6 -3
- package/serving/shared-three.ts +176 -0
- package/src/adapter/constraint.ts +1 -18
- package/src/adapter/object3d-authoring-subject.ts +1 -12
- package/src/adapter/reflection-probe.ts +1 -9
- package/src/adapter/three-contract.ts +6 -60
- package/src/animation/live-mixers.ts +0 -4
- package/src/api.ts +7 -0
- package/src/asset-loaders.ts +2 -178
- package/src/capture/photograph-sampling.ts +333 -0
- package/src/capture/scene.ts +1 -1
- package/src/ecs/object-marks.ts +6 -14
- package/src/ecs/user-data.ts +3 -138
- package/src/kit/animation/three-clips-subject.ts +19 -42
- package/src/kit/asset-compare-core.ts +161 -0
- package/src/kit/asset-compare.ts +8 -27
- package/src/kit/asset-preview-command.ts +14 -19
- package/src/kit/asset-preview-framing.ts +8 -67
- package/src/kit/asset-preview.ts +109 -342
- package/src/kit/asset-workflow/model-inspection.ts +11 -154
- package/src/kit/asset-workflow/preview-resource-lifetime.ts +25 -0
- package/src/kit/authoring/component-instance-root.ts +3 -39
- package/src/kit/authoring/live-object-transform.ts +1 -30
- package/src/kit/authoring/object3d-document-session-registry.ts +7 -15
- package/src/kit/authoring/object3d-document-session.ts +471 -208
- package/src/kit/authoring/shell-viewport-policy.ts +18 -24
- package/src/kit/authoring/source-object3d-authoring-adapter.ts +6 -48
- package/src/kit/authoring/three-projection-core.ts +11 -40
- package/src/kit/authoring/viewport-pick-context.ts +5 -12
- package/src/kit/authoring/viewport-raycast.ts +15 -93
- package/src/kit/authoring/world-hidden-viewport.ts +8 -61
- package/src/kit/capture-camera-pose.ts +68 -0
- package/src/kit/collaboration-presence.ts +41 -0
- package/src/kit/components/CameraInfo.tsx +4 -6
- package/src/kit/components/InspectorObjectPreview.tsx +3 -30
- package/src/kit/components/Object3DDocumentToolbar.css +75 -0
- package/src/kit/components/Object3DDocumentToolbar.tsx +18 -84
- package/src/kit/components/Object3DDocumentViewport.tsx +5 -8
- package/src/kit/components/StageHost.css +40 -0
- package/src/kit/components/StageHost.tsx +181 -404
- package/src/kit/components/StageOverlays.tsx +1 -2
- package/src/kit/components/StatsOverlay.tsx +5 -17
- package/src/kit/components/ViewportFurniture.tsx +27 -154
- package/src/kit/components/ViewportOverlay.tsx +13 -17
- package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
- package/src/kit/components/ViewportShadingMenu.tsx +2 -42
- package/src/kit/components/ViewportViewMenu.tsx +7 -18
- package/src/kit/components/asset-viewers/EntityModelDocument.tsx +4 -13
- package/src/kit/components/asset-viewers/EnvironmentAssetDocument.tsx +5 -5
- package/src/kit/components/asset-viewers/LiveModuleDocument.tsx +24 -102
- package/src/kit/components/asset-viewers/LutAssetDocument.tsx +6 -6
- package/src/kit/components/asset-viewers/Object3DPreview.tsx +10 -45
- package/src/kit/components/asset-viewers/QuarksAssetDocument.tsx +2 -2
- package/src/kit/components/asset-viewers/ShaderAssetDocument.tsx +11 -10
- package/src/kit/components/asset-viewers/shader-source.ts +144 -0
- package/src/kit/components/asset-viewers/three-asset-viewers.tsx +2 -14
- package/src/kit/components/object3d-contribution-surfaces.tsx +1 -1
- package/src/kit/components/stage-keyboard.tsx +6 -12
- package/src/kit/components/stage-overlay-set.tsx +11 -20
- package/src/kit/components/stage-presence-markers.ts +9 -32
- package/src/kit/components/stage-transform-chrome.ts +4 -4
- package/src/kit/components/stage-transform-tools.tsx +7 -14
- package/src/kit/components/standard-viewport-dressing.ts +47 -167
- package/src/kit/components/world-root-binding.ts +2 -7
- package/src/kit/constraint-helper.ts +1 -1
- package/src/kit/document-renderer-session.ts +114 -0
- package/src/kit/editor-presentation-activity.ts +58 -0
- package/src/kit/editor-shell-store.ts +31 -403
- package/src/kit/editor-viewport.ts +476 -1762
- package/src/kit/entity-lod.ts +3 -16
- package/src/kit/entity-object.ts +1 -39
- package/src/kit/hierarchy-mark-reader.ts +13 -30
- package/src/kit/instanced-presentation.ts +1 -47
- package/src/kit/live-gesture-lock.ts +35 -0
- package/src/kit/live-module-source.ts +12 -52
- package/src/kit/model-thumbnail.ts +7 -35
- package/src/kit/play-camera-flight.ts +7 -16
- package/src/kit/projection/three.ts +13 -366
- package/src/kit/retained-document-states.ts +91 -0
- package/src/kit/scene-document-viewport.ts +3 -3
- package/src/kit/scene-framing.ts +11 -152
- package/src/kit/scene-view-fog.ts +2 -47
- package/src/kit/spatial-handle-visuals.ts +19 -28
- package/src/kit/stories/three-story-model.ts +5 -33
- package/src/kit/three-canvas-render.ts +3 -4
- package/src/kit/three-hierarchy-row-media.ts +3 -11
- package/src/kit/three-inspection-media.ts +6 -6
- package/src/kit/three-integration.ts +18 -18
- package/src/kit/three-state.ts +2 -19
- package/src/kit/three-viewport/camera-fit.ts +2 -6
- package/src/kit/three-viewport/selection-brackets.ts +5 -20
- package/src/kit/three-viewport/selection-outline.ts +4 -56
- package/src/kit/three-viewport/skeleton-helper.ts +1 -32
- package/src/kit/three-viewport/source-color.ts +1 -33
- package/src/kit/three-viewport/studio-environment.ts +4 -55
- package/src/kit/three-viewport-presentation.ts +23 -0
- package/src/kit/transport-strip.tsx +147 -0
- package/src/kit/viewport-actions.ts +8 -50
- package/src/kit/viewport-authoring-policy.ts +5 -52
- package/src/kit/viewport-commands.ts +28 -57
- package/src/kit/viewport-hotkeys.ts +29 -31
- package/src/kit/viewport-status-facet.ts +4 -5
- package/src/kit/viewport-surface-status.tsx +44 -0
- package/src/loader.ts +8 -71
- package/src/object3d-contributions.ts +18 -34
- package/src/viewport/clip-planes.ts +4 -32
- package/src/viewport/content-bounds.ts +13 -142
- package/src/viewport/editor-layers.ts +4 -26
- package/src/viewport/environment.ts +1 -1
- package/src/viewport/preview-renderer.ts +7 -45
- package/src/viewport/renderer-ownership.ts +14 -62
- package/src/viewport-api.ts +14 -33
- package/src/viewport-door.ts +16 -86
- package/contributions/three-integration.service.ts +0 -13
- package/src/adapter/hierarchy-marks.ts +0 -156
- package/src/adapter/ingest/scene-capture.ts +0 -843
- package/src/adapter/ingest/structural-ids.ts +0 -139
- package/src/adapter/ingest/visible-capture-window.ts +0 -302
- package/src/adapter/renderer-config.ts +0 -115
- package/src/asset-parse-error.ts +0 -29
- package/src/host-hierarchy-objects.ts +0 -31
- package/src/kit/authoring/design-time-settle.ts +0 -343
- package/src/kit/camera-authoring.ts +0 -175
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/editor-threejs",
|
|
3
|
+
"publisher": "volter",
|
|
3
4
|
"author": "Volter AI, Inc.",
|
|
4
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.212",
|
|
6
|
+
"engines": {
|
|
7
|
+
"vscode": "*"
|
|
8
|
+
},
|
|
5
9
|
"publishConfig": {
|
|
6
10
|
"access": "public"
|
|
7
11
|
},
|
|
@@ -24,12 +28,16 @@
|
|
|
24
28
|
],
|
|
25
29
|
"exports": {
|
|
26
30
|
"./package.json": "./package.json",
|
|
31
|
+
"./api": "./src/api.ts",
|
|
27
32
|
"./contributions/*": "./contributions/*",
|
|
33
|
+
"./build/shared-three": {
|
|
34
|
+
"types": "./serving/shared-three.ts",
|
|
35
|
+
"default": "./dist-node/shared-three.mjs"
|
|
36
|
+
},
|
|
28
37
|
"./*": {
|
|
29
38
|
"types": "./src/*.ts",
|
|
30
39
|
"default": "./src/*"
|
|
31
40
|
},
|
|
32
|
-
"./asset-parse-error": "./src/asset-parse-error.ts",
|
|
33
41
|
"./loader": "./src/loader.ts",
|
|
34
42
|
"./kit/animation/three-clips-subject": "./src/kit/animation/three-clips-subject.ts",
|
|
35
43
|
"./kit/asset-compare": "./src/kit/asset-compare.ts",
|
|
@@ -38,7 +46,6 @@
|
|
|
38
46
|
"./kit/asset-preview": "./src/kit/asset-preview.ts",
|
|
39
47
|
"./kit/asset-workflow/model-inspection": "./src/kit/asset-workflow/model-inspection.ts",
|
|
40
48
|
"./kit/authoring/component-instance-root": "./src/kit/authoring/component-instance-root.ts",
|
|
41
|
-
"./kit/authoring/design-time-settle": "./src/kit/authoring/design-time-settle.ts",
|
|
42
49
|
"./kit/authoring/live-object-transform": "./src/kit/authoring/live-object-transform.ts",
|
|
43
50
|
"./kit/authoring/object3d-document-session-registry": "./src/kit/authoring/object3d-document-session-registry.ts",
|
|
44
51
|
"./kit/authoring/object3d-document-session": "./src/kit/authoring/object3d-document-session.ts",
|
|
@@ -49,7 +56,6 @@
|
|
|
49
56
|
"./kit/authoring/viewport-pick-context": "./src/kit/authoring/viewport-pick-context.ts",
|
|
50
57
|
"./kit/authoring/viewport-raycast": "./src/kit/authoring/viewport-raycast.ts",
|
|
51
58
|
"./kit/authoring/world-hidden-viewport": "./src/kit/authoring/world-hidden-viewport.ts",
|
|
52
|
-
"./kit/camera-authoring": "./src/kit/camera-authoring.ts",
|
|
53
59
|
"./kit/components/CameraInfo": "./src/kit/components/CameraInfo.tsx",
|
|
54
60
|
"./kit/components/InspectorObjectPreview": "./src/kit/components/InspectorObjectPreview.tsx",
|
|
55
61
|
"./kit/components/Object3DDocumentToolbar": "./src/kit/components/Object3DDocumentToolbar.tsx",
|
|
@@ -116,8 +122,8 @@
|
|
|
116
122
|
"./kit/viewport-status-facet": "./src/kit/viewport-status-facet.ts"
|
|
117
123
|
},
|
|
118
124
|
"peerDependencies": {
|
|
119
|
-
"three": "^0.
|
|
120
|
-
"vite": "^6.4.3",
|
|
125
|
+
"three": "^0.186.1",
|
|
126
|
+
"vite": "^6.4.3 || ^7.0.0 || ^8.0.0",
|
|
121
127
|
"react": "^19.0.0",
|
|
122
128
|
"react-dom": "^19.0.0"
|
|
123
129
|
},
|
|
@@ -126,22 +132,296 @@
|
|
|
126
132
|
"prepack": "npm run build",
|
|
127
133
|
"typecheck": "tsc -p tsconfig.json"
|
|
128
134
|
},
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
"contributes": {
|
|
136
|
+
"volter": {
|
|
137
|
+
"serving": [
|
|
138
|
+
"./dist-node/serving.mjs"
|
|
139
|
+
],
|
|
140
|
+
"page": [
|
|
141
|
+
"./contributions/three.page.ts"
|
|
142
|
+
],
|
|
143
|
+
"editors": [
|
|
144
|
+
{
|
|
145
|
+
"assetRoute": "model"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"assetRoute": "environment"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"assetRoute": "lut"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"assetRoute": "shader"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"assetRoute": "module"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"assetRoute": "entity-model"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"assetRoute": "json"
|
|
164
|
+
}
|
|
165
|
+
],
|
|
166
|
+
"views": {
|
|
167
|
+
"panel": [
|
|
168
|
+
{
|
|
169
|
+
"id": "animation-timeline",
|
|
170
|
+
"title": "Animation",
|
|
171
|
+
"module": "./contributions/animation-timeline.utility.tsx"
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
"services": [
|
|
176
|
+
"./contributions/animation-mixers.service.ts"
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
"commands": [
|
|
180
|
+
{
|
|
181
|
+
"command": "volter.focus-entity",
|
|
182
|
+
"title": "focus-entity",
|
|
183
|
+
"category": "Three Viewport",
|
|
184
|
+
"volter": {
|
|
185
|
+
"derivedRefresh": "none"
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"command": "volter.frame-entity",
|
|
190
|
+
"title": "frame-entity",
|
|
191
|
+
"category": "Three Viewport",
|
|
192
|
+
"volter": {
|
|
193
|
+
"derivedRefresh": "none"
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"command": "volter.focus-selection",
|
|
198
|
+
"title": "focus-selection",
|
|
199
|
+
"category": "Three Viewport",
|
|
200
|
+
"volter": {
|
|
201
|
+
"derivedRefresh": "none"
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"command": "volter.view-preset",
|
|
206
|
+
"title": "view-preset",
|
|
207
|
+
"category": "Three Viewport",
|
|
208
|
+
"volter": {
|
|
209
|
+
"derivedRefresh": "none"
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"command": "volter.set-camera",
|
|
214
|
+
"title": "set-camera",
|
|
215
|
+
"category": "Three Viewport",
|
|
216
|
+
"volter": {
|
|
217
|
+
"derivedRefresh": "none"
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"command": "volter.document-orbit",
|
|
222
|
+
"title": "document-orbit",
|
|
223
|
+
"category": "Three Viewport",
|
|
224
|
+
"volter": {
|
|
225
|
+
"timeoutMs": 120000,
|
|
226
|
+
"derivedRefresh": "none"
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"command": "volter.document-turntable",
|
|
231
|
+
"title": "document-turntable",
|
|
232
|
+
"category": "Three Viewport",
|
|
233
|
+
"volter": {
|
|
234
|
+
"timeoutMs": 120000,
|
|
235
|
+
"derivedRefresh": "none"
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"command": "volter.document-frame",
|
|
240
|
+
"title": "document-frame",
|
|
241
|
+
"category": "Three Viewport",
|
|
242
|
+
"volter": {
|
|
243
|
+
"derivedRefresh": "none"
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"command": "volter.document-frame-cost",
|
|
248
|
+
"title": "document-frame-cost",
|
|
249
|
+
"category": "Three Viewport",
|
|
250
|
+
"volter": {
|
|
251
|
+
"timeoutMs": 120000,
|
|
252
|
+
"derivedRefresh": "none"
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"command": "volter.capture-viewport",
|
|
257
|
+
"title": "capture-viewport",
|
|
258
|
+
"category": "Three Viewport",
|
|
259
|
+
"volter": {
|
|
260
|
+
"derivedRefresh": "if-content-changed"
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"command": "volter.capture-asset-preview",
|
|
265
|
+
"title": "capture-asset-preview",
|
|
266
|
+
"category": "Three Viewport",
|
|
267
|
+
"volter": {
|
|
268
|
+
"timeoutMs": 30000,
|
|
269
|
+
"derivedRefresh": "if-content-changed"
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"command": "volter.set-grid",
|
|
274
|
+
"title": "set-grid",
|
|
275
|
+
"category": "Three Viewport",
|
|
276
|
+
"volter": {
|
|
277
|
+
"derivedRefresh": "none"
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"command": "volter.set-helpers",
|
|
282
|
+
"title": "set-helpers",
|
|
283
|
+
"category": "Three Viewport",
|
|
284
|
+
"volter": {
|
|
285
|
+
"derivedRefresh": "none"
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"command": "volter.set-stats",
|
|
290
|
+
"title": "set-stats",
|
|
291
|
+
"category": "Three Viewport",
|
|
292
|
+
"volter": {
|
|
293
|
+
"derivedRefresh": "none"
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"command": "volter.set-shading-mode",
|
|
298
|
+
"title": "set-shading-mode",
|
|
299
|
+
"category": "Three Viewport",
|
|
300
|
+
"volter": {
|
|
301
|
+
"derivedRefresh": "none"
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"command": "volter.set-helper-type",
|
|
306
|
+
"title": "set-helper-type",
|
|
307
|
+
"category": "Three Viewport",
|
|
308
|
+
"volter": {
|
|
309
|
+
"derivedRefresh": "none"
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"command": "volter.set-transform-mode",
|
|
314
|
+
"title": "set-transform-mode",
|
|
315
|
+
"category": "Three Viewport",
|
|
316
|
+
"volter": {
|
|
317
|
+
"derivedRefresh": "none"
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"command": "volter.set-transform-space",
|
|
322
|
+
"title": "set-transform-space",
|
|
323
|
+
"category": "Three Viewport",
|
|
324
|
+
"volter": {
|
|
325
|
+
"derivedRefresh": "none"
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"command": "volter.set-snap",
|
|
330
|
+
"title": "set-snap",
|
|
331
|
+
"category": "Three Viewport",
|
|
332
|
+
"volter": {
|
|
333
|
+
"derivedRefresh": "none"
|
|
334
|
+
}
|
|
335
|
+
}
|
|
134
336
|
],
|
|
135
|
-
"
|
|
337
|
+
"menus": {
|
|
338
|
+
"commandPalette": [
|
|
339
|
+
{
|
|
340
|
+
"command": "volter.focus-entity",
|
|
341
|
+
"when": "false"
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
"command": "volter.frame-entity",
|
|
345
|
+
"when": "false"
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"command": "volter.focus-selection",
|
|
349
|
+
"when": "false"
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"command": "volter.view-preset",
|
|
353
|
+
"when": "false"
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"command": "volter.set-camera",
|
|
357
|
+
"when": "false"
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"command": "volter.document-orbit",
|
|
361
|
+
"when": "false"
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"command": "volter.document-turntable",
|
|
365
|
+
"when": "false"
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
"command": "volter.document-frame",
|
|
369
|
+
"when": "false"
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"command": "volter.document-frame-cost",
|
|
373
|
+
"when": "false"
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"command": "volter.capture-viewport",
|
|
377
|
+
"when": "false"
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"command": "volter.capture-asset-preview",
|
|
381
|
+
"when": "false"
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
"command": "volter.set-grid",
|
|
385
|
+
"when": "false"
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"command": "volter.set-helpers",
|
|
389
|
+
"when": "false"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"command": "volter.set-stats",
|
|
393
|
+
"when": "false"
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
"command": "volter.set-shading-mode",
|
|
397
|
+
"when": "false"
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
"command": "volter.set-helper-type",
|
|
401
|
+
"when": "false"
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"command": "volter.set-transform-mode",
|
|
405
|
+
"when": "false"
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"command": "volter.set-transform-space",
|
|
409
|
+
"when": "false"
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"command": "volter.set-snap",
|
|
413
|
+
"when": "false"
|
|
414
|
+
}
|
|
415
|
+
]
|
|
416
|
+
}
|
|
136
417
|
},
|
|
137
418
|
"dependencies": {
|
|
138
|
-
"@volter/project": "0.5.
|
|
419
|
+
"@volter/project": "0.5.212",
|
|
139
420
|
"@sparkjsdev/spark": "^2.1.0",
|
|
140
421
|
"three.quarks": "^0.16.0",
|
|
141
|
-
"zod": "^4.3.6",
|
|
142
422
|
"typescript": "5.9.3",
|
|
143
|
-
"@volter/sdk": "0.5.
|
|
144
|
-
"postprocessing": "6.
|
|
423
|
+
"@volter/sdk": "0.5.212",
|
|
424
|
+
"postprocessing": "6.39.5",
|
|
145
425
|
"quarks.core": "0.16.0",
|
|
146
426
|
"@fortawesome/free-solid-svg-icons": "^7.2.0"
|
|
147
427
|
},
|
|
@@ -36,7 +36,7 @@ function isUseAnimations(node: ts.Node): node is ts.CallExpression {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/** Wrap every mixer a module makes; `null` when it makes none. */
|
|
39
|
-
|
|
39
|
+
function stampAnimation(code: string, file: string, relativeFile: string): string | null {
|
|
40
40
|
if (!code.includes('AnimationMixer') && !code.includes('useAnimations')) return null;
|
|
41
41
|
const kind = file.endsWith('.tsx') ? ts.ScriptKind.TSX : file.endsWith('.jsx') ? ts.ScriptKind.JSX : ts.ScriptKind.TS;
|
|
42
42
|
const source = ts.createSourceFile(file, code, ts.ScriptTarget.Latest, true, kind);
|
package/serving/index.ts
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@volter/editor-threejs`'s server half (`package.json#volter.serving`): the animation stamp that
|
|
3
|
-
* lets the editor drive the mixers a project's own code makes,
|
|
4
|
-
* formats to runtime GLB for the asset library's imports.
|
|
2
|
+
* `@volter/editor-threejs`'s server half (`package.json#contributes.volter.serving`): the animation stamp that
|
|
3
|
+
* lets the editor drive the mixers a project's own code makes, the conversion of source model
|
|
4
|
+
* formats to runtime GLB for the asset library's imports, and one three.js for the page, the
|
|
5
|
+
* shell's, with the project graph's three and Fiber deduped (`shared-three.ts`). It registers the
|
|
6
|
+
* `three` substrate, the `stage` surface's default row.
|
|
5
7
|
*/
|
|
6
8
|
|
|
7
|
-
import type { ProjectServingServices } from '@volter/sdk/session/project-serving';
|
|
9
|
+
import type { ProjectServingModule, ProjectServingServices } from '@volter/sdk/session/project-serving';
|
|
8
10
|
import { animationStampPlugin } from './animation-stamp';
|
|
9
11
|
import { threeModelConverter } from './model-import-conversion';
|
|
12
|
+
import { sharedThreeServingPlugins } from './shared-three';
|
|
10
13
|
|
|
11
14
|
export const servingPlugins = (services: ProjectServingServices): readonly unknown[] => {
|
|
12
15
|
services.registerModelConverter(threeModelConverter);
|
|
13
|
-
return [animationStampPlugin(services)];
|
|
16
|
+
return [...sharedThreeServingPlugins(services.shellOutputDir), animationStampPlugin(services)];
|
|
14
17
|
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The `three` substrate: the `stage` surface's default row, authored in the `r3f` dialect through
|
|
21
|
+
* the source-prop, structural and construction-literal anchors. A folder that depends on `three` or `@react-three/fiber` already
|
|
22
|
+
* uses it.
|
|
23
|
+
*/
|
|
24
|
+
export const substrates: ProjectServingModule['substrates'] = [
|
|
25
|
+
{
|
|
26
|
+
substrate: 'three',
|
|
27
|
+
surface: 'stage',
|
|
28
|
+
dialects: ['r3f'],
|
|
29
|
+
default: { dialect: 'r3f', anchors: ['source-prop', 'source-structure', 'construction-literal'] },
|
|
30
|
+
},
|
|
31
|
+
];
|
|
@@ -24,7 +24,7 @@ export const threeModelConverter: ModelConverter = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
/** Convert a staged source model to a runtime GLB without requiring Blender. */
|
|
27
|
-
|
|
27
|
+
async function convertStagedModelToGlb(
|
|
28
28
|
primaryPath: string,
|
|
29
29
|
format: string,
|
|
30
30
|
settings: ModelImportSettings,
|
|
@@ -71,7 +71,7 @@ const materialTextureSlots = [
|
|
|
71
71
|
] as const;
|
|
72
72
|
|
|
73
73
|
/** Apply the persisted conversion settings before the runtime GLB is exported. */
|
|
74
|
-
|
|
74
|
+
function applyModelImportSettings(
|
|
75
75
|
object: THREE.Object3D,
|
|
76
76
|
settings: ModelImportSettings,
|
|
77
77
|
): void {
|
|
@@ -205,7 +205,10 @@ async function parseSourceModel(
|
|
|
205
205
|
return loader.parse(new TextDecoder().decode(bytes));
|
|
206
206
|
}
|
|
207
207
|
case 'dae': {
|
|
208
|
-
|
|
208
|
+
const collada = new ColladaLoader().parse(new TextDecoder().decode(bytes), resourcePath);
|
|
209
|
+
// The loader answers null for a file that is not a COLLADA document (stated in r186's types).
|
|
210
|
+
if (!collada) throw new Error(`${primaryPath} is not a COLLADA document`);
|
|
211
|
+
return collada.scene;
|
|
209
212
|
}
|
|
210
213
|
case 'stl': {
|
|
211
214
|
const geometry = new STLLoader().parse(bytes.buffer as ArrayBuffer);
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Share the built shell’s three.js instance with the project module graph. The build emits main and
|
|
3
|
+
* core doorway chunks from the shell’s module graph and records their URLs in a manifest. The
|
|
4
|
+
* serving plugin resolves project three imports to those URLs and excludes three from dependency
|
|
5
|
+
* prebundling so nested imports use the same instance. Source-served shells use Vite deduplication.
|
|
6
|
+
* Prebuilt project bundles that inline three do not pass through this resolution.
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { createRequire } from 'node:module';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import type { Plugin } from 'vite';
|
|
12
|
+
import { sharedDoorwayId } from '@volter/sdk/shared-doorway';
|
|
13
|
+
import { installedExportNames, sharedEntryModule } from '@volter/sdk/shared-entry-module';
|
|
14
|
+
|
|
15
|
+
/** The bare specifier this plugin owns. three's `window.__THREE__` guard lives
|
|
16
|
+
* in its main entry (`three/build/three.core.js`, re-exported by `three`), so
|
|
17
|
+
* collapsing the main entry collapses the duplicate-instance warning; addons
|
|
18
|
+
* (`three/addons/*`, `three/examples/jsm/*`) import bare `three` internally and
|
|
19
|
+
* ride this same redirect. */
|
|
20
|
+
const SHARED_THREE_SPECIFIER = 'three';
|
|
21
|
+
|
|
22
|
+
/** The rollup chunk NAME the shell's three is emitted under. */
|
|
23
|
+
const SHARED_THREE_ENTRY_NAME = 'volter-shared-three';
|
|
24
|
+
|
|
25
|
+
/** The emitted three.js chunk manifest, written beside the built shell. */
|
|
26
|
+
const SHARED_THREE_MANIFEST_FILE = 'volter-shared-three.json';
|
|
27
|
+
|
|
28
|
+
interface SharedThreeManifest {
|
|
29
|
+
/** outDir-relative built chunk file (`assets/…js`) for `three`. */
|
|
30
|
+
file: string;
|
|
31
|
+
/** The same build's core exports, including internals needed by three/webgpu. */
|
|
32
|
+
coreFile: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const VIRTUAL_PREFIX = '\0volter-shared-three:';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* BUILD side: emit the `three` entry chunk and the manifest naming it.
|
|
39
|
+
*
|
|
40
|
+
* `fromDir` is the directory whose `node_modules` the three being published
|
|
41
|
+
* comes from — the repo root for this build, which is the same three the shell
|
|
42
|
+
* itself bundles. The entry body is generated from the installed package's own
|
|
43
|
+
* runtime key list ({@link sharedEntryModule} / {@link installedExportNames}), so
|
|
44
|
+
* it cannot drift from the installed three and needs no hand-maintained export list.
|
|
45
|
+
*/
|
|
46
|
+
export function sharedThreeBuildPlugin(fromDir: string): Plugin {
|
|
47
|
+
let referenceId: string;
|
|
48
|
+
let coreReferenceId: string;
|
|
49
|
+
return {
|
|
50
|
+
name: 'volter-shared-three-build',
|
|
51
|
+
apply: 'build',
|
|
52
|
+
buildStart() {
|
|
53
|
+
// A direct core entry shares Rollup's module identity with the shell's WebGL entry.
|
|
54
|
+
// WebGPU needs core exports that the public `three` entry does not re-export.
|
|
55
|
+
const require_ = createRequire(path.join(fromDir, 'package.json'));
|
|
56
|
+
coreReferenceId = this.emitFile({
|
|
57
|
+
type: 'chunk',
|
|
58
|
+
id: path.join(path.dirname(require_.resolve('three')), 'three.core.js'),
|
|
59
|
+
name: 'volter-shared-three-core',
|
|
60
|
+
preserveSignature: 'strict',
|
|
61
|
+
});
|
|
62
|
+
referenceId = this.emitFile({
|
|
63
|
+
type: 'chunk',
|
|
64
|
+
id: `${VIRTUAL_PREFIX}${SHARED_THREE_SPECIFIER}`,
|
|
65
|
+
name: SHARED_THREE_ENTRY_NAME,
|
|
66
|
+
// Same reason as the shared-React entries: Vite's app build sets
|
|
67
|
+
// `preserveEntrySignatures: false`, which would mangle the entry's
|
|
68
|
+
// export names away — `strict` keeps `Mesh` spelled `Mesh`.
|
|
69
|
+
preserveSignature: 'strict',
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
resolveId(id) {
|
|
73
|
+
return id.startsWith(VIRTUAL_PREFIX) ? id : undefined;
|
|
74
|
+
},
|
|
75
|
+
load(id) {
|
|
76
|
+
if (!id.startsWith(VIRTUAL_PREFIX)) return undefined;
|
|
77
|
+
const specifier = id.slice(VIRTUAL_PREFIX.length);
|
|
78
|
+
return sharedEntryModule(specifier, installedExportNames(fromDir, specifier));
|
|
79
|
+
},
|
|
80
|
+
generateBundle() {
|
|
81
|
+
this.emitFile({
|
|
82
|
+
type: 'asset',
|
|
83
|
+
fileName: SHARED_THREE_MANIFEST_FILE,
|
|
84
|
+
source: `${JSON.stringify(
|
|
85
|
+
{ file: this.getFileName(referenceId), coreFile: this.getFileName(coreReferenceId) } satisfies SharedThreeManifest,
|
|
86
|
+
null,
|
|
87
|
+
2,
|
|
88
|
+
)}\n`,
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Read the three.js manifest from a built shell. */
|
|
95
|
+
function readSharedThreeManifest(distPath: string): SharedThreeManifest {
|
|
96
|
+
const manifestPath = path.join(distPath, SHARED_THREE_MANIFEST_FILE);
|
|
97
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as Partial<SharedThreeManifest>;
|
|
98
|
+
if (typeof manifest.file !== 'string' || !manifest.file || typeof manifest.coreFile !== 'string' || !manifest.coreFile)
|
|
99
|
+
throw new Error(`${manifestPath} must name the shared three.js and core chunks. Rebuild the editor.`);
|
|
100
|
+
return { file: manifest.file, coreFile: manifest.coreFile };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Use the built shell’s root-relative chunk URL so both module graphs share its identity. */
|
|
104
|
+
function sharedThreeUrl(file: string): string {
|
|
105
|
+
return `/${file}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** The stable module every project-graph `three` import resolves to; only it imports the hashed
|
|
109
|
+
* chunk. Its id follows the shared-doorway rule (`\0volter-shared:<specifier>`), which the
|
|
110
|
+
* limited view's live compiler reads to find a shared module's recording. Browsers keep
|
|
111
|
+
* prebundled chunks naming this id for as long as their `?v=` stands, so renaming it must rename
|
|
112
|
+
* the plugin too (which moves `?v=`), or those chunks import a module that no longer answers. */
|
|
113
|
+
const SHARED_THREE_DOORWAY = sharedDoorwayId(SHARED_THREE_SPECIFIER);
|
|
114
|
+
const SHARED_THREE_CORE_DOORWAY = sharedDoorwayId('three/build/three.core.js');
|
|
115
|
+
|
|
116
|
+
/** Resolve project three imports through a stable, revalidated doorway that re-exports the shell’s hashed chunk. Cached dependency bodies retain the doorway URL across shell builds while shell and project share one module instance. */
|
|
117
|
+
function sharedThreePlugin(url: string, coreUrl: string): Plugin {
|
|
118
|
+
return {
|
|
119
|
+
// Vite includes this plugin name in the dependency cache version.
|
|
120
|
+
name: 'volter-shared:three',
|
|
121
|
+
enforce: 'pre',
|
|
122
|
+
// `three` is the shell's here, never prebundled: excluding it externalizes it out of every
|
|
123
|
+
// prebundled chunk (Fiber's own `import 'three'` included), so those imports resolve at serve
|
|
124
|
+
// time through this plugin. A specifier cannot be both included and excluded.
|
|
125
|
+
config(config) {
|
|
126
|
+
const optimizeDeps = (config.optimizeDeps ??= {});
|
|
127
|
+
optimizeDeps.include = (optimizeDeps.include ?? []).filter((specifier) => specifier !== SHARED_THREE_SPECIFIER);
|
|
128
|
+
optimizeDeps.exclude = [...(optimizeDeps.exclude ?? []), SHARED_THREE_SPECIFIER];
|
|
129
|
+
},
|
|
130
|
+
load(id) {
|
|
131
|
+
if (id === SHARED_THREE_CORE_DOORWAY) return `export * from ${JSON.stringify(coreUrl)};\n`;
|
|
132
|
+
// The chunk also has a default export (the namespace, `sharedEntryModule`), which
|
|
133
|
+
// `export *` leaves out; preserve it for a project’s default import.
|
|
134
|
+
return id === SHARED_THREE_DOORWAY
|
|
135
|
+
? `export * from ${JSON.stringify(SHARED_THREE_SPECIFIER)};\nexport { default } from ${JSON.stringify(SHARED_THREE_SPECIFIER)};\n`
|
|
136
|
+
: undefined;
|
|
137
|
+
},
|
|
138
|
+
resolveId(source, importer, options) {
|
|
139
|
+
if (importer === SHARED_THREE_CORE_DOORWAY && source === coreUrl) return coreUrl;
|
|
140
|
+
const cleanSource = source.split('?')[0]!.replaceAll('\\', '/');
|
|
141
|
+
const cleanImporter = (importer ?? '').split('?')[0]!.replaceAll('\\', '/');
|
|
142
|
+
// three/webgpu's relative core import must share the shell's core too.
|
|
143
|
+
const core = /(?:^|\/)three\/build\/three\.core\.js$/.test(cleanSource) ||
|
|
144
|
+
(cleanSource === './three.core.js' && /\/three\/build\/three\.[^/]+\.js$/.test(cleanImporter));
|
|
145
|
+
if (source !== SHARED_THREE_SPECIFIER && !core) return undefined;
|
|
146
|
+
// Let Vite’s dependency scanner resolve files normally. The excluded dependency is
|
|
147
|
+
// redirected at serve time; an asset URL is not a file the scanner can prebundle.
|
|
148
|
+
if ((options as { scan?: boolean } | undefined)?.scan) return undefined;
|
|
149
|
+
if (core) return SHARED_THREE_CORE_DOORWAY;
|
|
150
|
+
return importer === SHARED_THREE_DOORWAY ? url : SHARED_THREE_DOORWAY;
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* ONE three, Fiber and Fiber context bridge for the project graph, however it was installed. The
|
|
157
|
+
* session's Vite runs with `configFile: false`, so the project's own config does not state it:
|
|
158
|
+
* Fiber, Drei, the installed engine and the world must share these instances, and a nested copy
|
|
159
|
+
* that resolution walks into collapses onto the one Vite resolves from the project root. Vite
|
|
160
|
+
* merges a `config()` result into the session's config, concatenating `resolve.dedupe` with the
|
|
161
|
+
* session's own rows.
|
|
162
|
+
*/
|
|
163
|
+
function projectThreeDedupePlugin(): Plugin {
|
|
164
|
+
return {
|
|
165
|
+
name: 'volter-three-dedupe',
|
|
166
|
+
config: () => ({ resolve: { dedupe: [SHARED_THREE_SPECIFIER, '@react-three/fiber', 'its-fine'] } }),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Install project renderer deduplication and, for built shells, the shared-three doorway. Source-serving sessions have no built doorway. */
|
|
171
|
+
export function sharedThreeServingPlugins(shellOutputDir: string | null): Plugin[] {
|
|
172
|
+
const dedupe = projectThreeDedupePlugin();
|
|
173
|
+
if (shellOutputDir === null) return [dedupe];
|
|
174
|
+
const manifest = readSharedThreeManifest(shellOutputDir);
|
|
175
|
+
return [dedupe, sharedThreePlugin(sharedThreeUrl(manifest.file), sharedThreeUrl(manifest.coreFile))];
|
|
176
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* pole Object3Ds remain the only source of truth.
|
|
9
9
|
*/
|
|
10
10
|
import type * as THREE from 'three';
|
|
11
|
-
import {
|
|
11
|
+
import { getUserData } from '../ecs/user-data';
|
|
12
12
|
|
|
13
13
|
export type ConstraintStatus = 'ready' | 'disabled' | 'unresolved' | 'error';
|
|
14
14
|
|
|
@@ -59,20 +59,3 @@ export function constraintsOf(
|
|
|
59
59
|
Boolean((entry as Partial<ConstraintMark>).config),
|
|
60
60
|
);
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
/** Add or replace one constraint mark without disturbing sibling constraints. */
|
|
64
|
-
export function setConstraintMark(object: THREE.Object3D, mark: ConstraintMark): void {
|
|
65
|
-
const next = constraintsOf(object).filter((entry) => entry.config.id !== mark.config.id);
|
|
66
|
-
setUserData(object, 'constraints', [...next, mark]);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Remove one mark, or the whole live projection when no id is supplied. */
|
|
70
|
-
export function clearConstraintMark(object: THREE.Object3D, id?: string): void {
|
|
71
|
-
if (id === undefined) {
|
|
72
|
-
deleteUserData(object, 'constraints');
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
const next = constraintsOf(object).filter((entry) => entry.config.id !== id);
|
|
76
|
-
if (next.length === 0) deleteUserData(object, 'constraints');
|
|
77
|
-
else setUserData(object, 'constraints', next);
|
|
78
|
-
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import type { PropertyDescriptor } from '@volter/project/adapter/authoring';
|
|
17
17
|
import type * as THREE from 'three';
|
|
18
|
-
import {
|
|
18
|
+
import { getUserData } from '../ecs/user-data';
|
|
19
19
|
|
|
20
20
|
export interface Object3DAuthoringSubjectField extends PropertyDescriptor {
|
|
21
21
|
/** Read the current value from the native subject. */
|
|
@@ -37,14 +37,3 @@ export function object3DAuthoringSubjectOf(
|
|
|
37
37
|
const mark = getUserData(object, 'authoringSubject');
|
|
38
38
|
return mark && typeof mark.label === 'string' && typeof mark.kind === 'string' ? mark : null;
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
export function setObject3DAuthoringSubject(
|
|
42
|
-
object: THREE.Object3D,
|
|
43
|
-
mark: Object3DAuthoringSubjectMark,
|
|
44
|
-
): void {
|
|
45
|
-
setUserData(object, 'authoringSubject', mark);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function clearObject3DAuthoringSubject(object: THREE.Object3D): void {
|
|
49
|
-
deleteUserData(object, 'authoringSubject');
|
|
50
|
-
}
|