@liveroom-tech/react-immersive 5.0.2 → 5.2.0
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.md +1030 -59
- package/dist/binding-builder.css +1 -1
- package/dist/binding-builder.js +17 -12
- package/dist/binding-builder.mjs +1 -1
- package/dist/chunk-4NLJSD3S.mjs +1 -0
- package/dist/chunk-B7REIGDG.mjs +1 -0
- package/dist/chunk-HYFJ5DYJ.mjs +1 -0
- package/dist/chunk-QC3NT76G.mjs +3 -0
- package/dist/chunk-T3M3BQ7H.mjs +32 -0
- package/dist/chunk-ZPK67UG7.mjs +1 -0
- package/dist/hosted.css +1 -1
- package/dist/hosted.d.mts +4 -3
- package/dist/hosted.d.ts +4 -3
- package/dist/hosted.js +16 -11
- package/dist/hosted.mjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.mts +85 -10
- package/dist/index.d.ts +85 -10
- package/dist/index.js +15 -10
- package/dist/index.mjs +1 -1
- package/dist/materialVariants-DnZe9eMC.d.mts +309 -0
- package/dist/materialVariants-DnZe9eMC.d.ts +309 -0
- package/dist/modelInfo-BYebMPdZ.d.mts +43 -0
- package/dist/modelInfo-XfUQO7C_.d.ts +43 -0
- package/dist/{ModelViewer-CbbJT85n.d.mts → modelViewerProps-CIZ2R_Fv.d.ts} +164 -43
- package/dist/{ModelViewer-DOexHkJC.d.ts → modelViewerProps-DoRiTZMn.d.mts} +164 -43
- package/dist/{objectCatalog-5W8n5xNQ.d.ts → rendererBackend-QwMzISTn.d.mts} +304 -5
- package/dist/{objectCatalog-5W8n5xNQ.d.mts → rendererBackend-QwMzISTn.d.ts} +304 -5
- package/dist/simple-model-viewer.css +1 -1
- package/dist/simple-model-viewer.d.mts +32 -4
- package/dist/simple-model-viewer.d.ts +32 -4
- package/dist/simple-model-viewer.js +3 -3
- package/dist/simple-model-viewer.mjs +1 -1
- package/dist/utils.d.mts +5 -4
- package/dist/utils.d.ts +5 -4
- package/dist/utils.js +1 -1
- package/dist/utils.mjs +1 -1
- package/package.json +2 -1
- package/dist/chunk-3GX7DOGS.mjs +0 -3
- package/dist/chunk-AH5NAZWX.mjs +0 -27
- package/dist/chunk-BGYK4Y2Y.mjs +0 -1
- package/dist/chunk-WFEYRUZC.mjs +0 -1
- package/dist/chunk-XTLSAYAQ.mjs +0 -1
- package/dist/modelInfo-CEmmvVCH.d.mts +0 -17
- package/dist/modelInfo-CEmmvVCH.d.ts +0 -17
|
@@ -1,9 +1,57 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { M as ModelFormat,
|
|
2
|
+
import { R as ReducedMotionSetting, c as ModelViewerLabels } from './materialVariants-DnZe9eMC.js';
|
|
3
|
+
import { V as ViewerLoading, c as ViewerReveal, M as ModelFormat, b as ViewerModelInfo } from './modelInfo-XfUQO7C_.js';
|
|
4
|
+
import { r as ObjectBindingDecal, Q as ObjectSurfacePoint, o as ObjectBinding, S as RendererBackend, ap as ViewerCameraState, Y as SceneAnnotationMarker, ar as ViewerObjectInfo, P as ObjectPointerEvent, n as ObjectActionEvent, e as AnimationControls, ao as ViewerCameraConfig, a1 as SceneConfig, aq as ViewerIsolation } from './rendererBackend-QwMzISTn.js';
|
|
4
5
|
import { CameraControls } from '@react-three/drei';
|
|
5
6
|
import { Object3D } from 'three';
|
|
6
7
|
|
|
8
|
+
/** Engagement from deliberate viewer interactions, with model/session context. */
|
|
9
|
+
type ViewerEngagementEvent = {
|
|
10
|
+
/** Ephemeral identifier for this viewer/model session; no persistent storage. */
|
|
11
|
+
sessionId: string;
|
|
12
|
+
/** ISO timestamp of the event. */
|
|
13
|
+
timestamp: string;
|
|
14
|
+
/** Milliseconds since tracking started for this model. */
|
|
15
|
+
elapsedMs: number;
|
|
16
|
+
modelUrl: string;
|
|
17
|
+
tilesetUrl: string | null;
|
|
18
|
+
} & ({
|
|
19
|
+
type: "part-viewed";
|
|
20
|
+
objectId: string;
|
|
21
|
+
objectKey: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
source: "canvas" | "panel" | "keyboard";
|
|
24
|
+
} | {
|
|
25
|
+
type: "variant-chosen";
|
|
26
|
+
/** The variant chosen; null when a group's choice was cleared. */
|
|
27
|
+
variant: string | null;
|
|
28
|
+
/** The group's previous choice. */
|
|
29
|
+
previousVariant: string | null;
|
|
30
|
+
/** The option group's name; null for a group without one. */
|
|
31
|
+
group: string | null;
|
|
32
|
+
} | {
|
|
33
|
+
type: "ar-started";
|
|
34
|
+
} | {
|
|
35
|
+
type: "ar-ended";
|
|
36
|
+
durationMs: number;
|
|
37
|
+
reason: "session-ended" | "interrupted";
|
|
38
|
+
} | {
|
|
39
|
+
type: "ar-launch-requested";
|
|
40
|
+
channel: "quick-look" | "mobile-handoff";
|
|
41
|
+
} | {
|
|
42
|
+
type: "tour-started";
|
|
43
|
+
annotationCount: number;
|
|
44
|
+
} | {
|
|
45
|
+
type: "tour-completed";
|
|
46
|
+
annotationCount: number;
|
|
47
|
+
durationMs: number;
|
|
48
|
+
} | {
|
|
49
|
+
type: "tour-stopped";
|
|
50
|
+
annotationCount: number;
|
|
51
|
+
durationMs: number;
|
|
52
|
+
reason: "stopped" | "restarted" | "annotations-changed" | "interrupted";
|
|
53
|
+
});
|
|
54
|
+
|
|
7
55
|
type CameraLimits = {
|
|
8
56
|
/** Closest the camera can get to its target, in scene units. Default 0. */
|
|
9
57
|
minDistance?: number;
|
|
@@ -49,6 +97,8 @@ type ModelViewerUiOptions = {
|
|
|
49
97
|
download?: boolean | string;
|
|
50
98
|
/** The reset-view button. Default `true`. */
|
|
51
99
|
reset?: boolean;
|
|
100
|
+
/** The viewer fullscreen toggle in the action bar. Default `false`. */
|
|
101
|
+
fullscreen?: boolean;
|
|
52
102
|
/** The loading overlay and load-error message. Default `true`. */
|
|
53
103
|
loadingOverlay?: boolean;
|
|
54
104
|
/** The axis gizmo in the top-right corner. Default `false`. */
|
|
@@ -62,8 +112,17 @@ type ModelViewerUiOptions = {
|
|
|
62
112
|
annotationNavigation?: boolean;
|
|
63
113
|
/** Show an annotation's details when its marker is hovered. Default `false`. */
|
|
64
114
|
annotationOnHover?: boolean;
|
|
115
|
+
/** Category filter chips. Default `true` when annotations have categories. */
|
|
116
|
+
annotationFilters?: boolean;
|
|
65
117
|
/** Highlight objects under the pointer. Default `true`. */
|
|
66
118
|
highlightOnHover?: boolean;
|
|
119
|
+
/** Swatch rows for the model's glTF material variants, one per option group. Default `true`. */
|
|
120
|
+
materialVariants?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* A tab stop for moving through and selecting objects with the keyboard,
|
|
123
|
+
* shown only while it has focus. Default `true`.
|
|
124
|
+
*/
|
|
125
|
+
objectNavigator?: boolean;
|
|
67
126
|
};
|
|
68
127
|
/**
|
|
69
128
|
* Takes over parts of texture positioning (`texturePositioning`). Fields left
|
|
@@ -92,6 +151,10 @@ type ModelViewerToolsOptions = {
|
|
|
92
151
|
uvChecker?: boolean;
|
|
93
152
|
/** The exploded-view slider. Default `false`. */
|
|
94
153
|
explode?: boolean;
|
|
154
|
+
/** The section-cut tool, to cut the model open along an axis. Default `false`. */
|
|
155
|
+
section?: boolean;
|
|
156
|
+
/** Isolate buttons in the scene objects panel, and a "Show all" pill. Default `false`. */
|
|
157
|
+
isolate?: boolean;
|
|
95
158
|
/** Texture offset, rotation and Move/Zoom for textured objects. Default `false`. */
|
|
96
159
|
texturePositioning?: boolean | TexturePositioningControls;
|
|
97
160
|
};
|
|
@@ -100,13 +163,19 @@ type ModelViewerControlsOptions = {
|
|
|
100
163
|
enabled?: boolean;
|
|
101
164
|
/** Move the camera with the keyboard while the canvas has focus. Default `false`. */
|
|
102
165
|
keyboard?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Cut motion the viewer starts on its own (auto-rotate, cinematic autoplay,
|
|
168
|
+
* camera glides). `"user"` follows the visitor's reduced-motion setting.
|
|
169
|
+
* Default `"user"`.
|
|
170
|
+
*/
|
|
171
|
+
reducedMotion?: ReducedMotionSetting;
|
|
103
172
|
/** Allow zooming. Default `true`. */
|
|
104
173
|
zoom?: boolean;
|
|
105
174
|
/** Zoom to an object when it's selected. Default `true`. */
|
|
106
175
|
zoomOnSelect?: boolean;
|
|
107
176
|
/** Turn the model slowly; a number sets the speed (1 is normal). Default `false`. */
|
|
108
177
|
autoRotate?: boolean | number;
|
|
109
|
-
/** Re-frame the model when the viewer is resized. Default `true`. */
|
|
178
|
+
/** Re-frame the model, or the selected object it zoomed to, when the viewer is resized. Default `true`. */
|
|
110
179
|
refitOnResize?: boolean;
|
|
111
180
|
/** Distance, angle and pan limits for the camera. */
|
|
112
181
|
limits?: CameraLimits;
|
|
@@ -124,6 +193,12 @@ type ModelViewerPerfOptions = {
|
|
|
124
193
|
profile?: PerformanceProfile;
|
|
125
194
|
/** Needed for Download PNG and captureImage; costs GPU time. Default `false`. */
|
|
126
195
|
preserveDrawingBuffer?: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Draw with three's WebGPU renderer where the browser has WebGPU, WebGL
|
|
198
|
+
* elsewhere. Leaves out post-processing effects, contact shadows and WebXR.
|
|
199
|
+
* Default `false`.
|
|
200
|
+
*/
|
|
201
|
+
webgpu?: boolean;
|
|
127
202
|
};
|
|
128
203
|
type ModelViewerTilesOptions = {
|
|
129
204
|
/** A 3D Tiles `tileset.json` to stream instead of loading `modelUrl` whole. */
|
|
@@ -168,6 +243,13 @@ type GroupedModelViewerProps = {
|
|
|
168
243
|
/** What each preset sets. Props that aren't listed keep their defaults. */
|
|
169
244
|
declare const MODEL_VIEWER_PRESETS: Readonly<Record<ModelViewerPreset, Readonly<Partial<ModelViewerProps>>>>;
|
|
170
245
|
|
|
246
|
+
type DecalMoveTarget = {
|
|
247
|
+
objectId: string;
|
|
248
|
+
decal: ObjectBindingDecal;
|
|
249
|
+
onCommit: (surface: ObjectSurfacePoint) => void;
|
|
250
|
+
onCancel: () => void;
|
|
251
|
+
};
|
|
252
|
+
|
|
171
253
|
type CameraControllerType = "orbit" | "pointerLock";
|
|
172
254
|
|
|
173
255
|
type CinematicWaypoint = {
|
|
@@ -195,6 +277,32 @@ type CaptureImageOptions = {
|
|
|
195
277
|
transparent?: boolean;
|
|
196
278
|
};
|
|
197
279
|
|
|
280
|
+
type CaptureVideoOptions = {
|
|
281
|
+
/** Defaults to cinematic when a path is enabled, otherwise turntable. */
|
|
282
|
+
mode?: "cinematic" | "turntable";
|
|
283
|
+
/**
|
|
284
|
+
* Auto prefers WebM, then MP4. `"gif"` makes an animated GIF that loops
|
|
285
|
+
* forever. Explicit formats reject if unsupported.
|
|
286
|
+
*/
|
|
287
|
+
format?: "auto" | "webm" | "mp4" | "gif";
|
|
288
|
+
/**
|
|
289
|
+
* Seconds per pass, in (0, 300]. Defaults to path timing, or an orbit of
|
|
290
|
+
* 24s (8s for a GIF).
|
|
291
|
+
*/
|
|
292
|
+
duration?: number;
|
|
293
|
+
/** Capture frame rate, from 1 to 60. Default 30 (15 for a GIF). */
|
|
294
|
+
fps?: number;
|
|
295
|
+
/** Encoder target bitrate in bits per second. Default 8,000,000. Not used for GIFs. */
|
|
296
|
+
videoBitsPerSecond?: number;
|
|
297
|
+
/**
|
|
298
|
+
* GIF width in pixels, from 16 to 4096; the height follows the canvas. Never
|
|
299
|
+
* wider than the canvas. Default 480.
|
|
300
|
+
*/
|
|
301
|
+
gifWidth?: number;
|
|
302
|
+
/** Aborting discards the recording and restores the viewer. */
|
|
303
|
+
signal?: AbortSignal;
|
|
304
|
+
};
|
|
305
|
+
|
|
198
306
|
type ViewerCameraPreset = {
|
|
199
307
|
position: [number, number, number];
|
|
200
308
|
target: [number, number, number];
|
|
@@ -221,7 +329,14 @@ type ViewerReadyState = {
|
|
|
221
329
|
objectBindings: Record<string, ObjectBinding>;
|
|
222
330
|
homeCameraState: HomeCameraState | null;
|
|
223
331
|
captureImage: (options?: CaptureImageOptions) => Promise<string>;
|
|
332
|
+
/** Records one cinematic pass or turntable revolution as a video Blob. */
|
|
333
|
+
captureVideo: (options?: CaptureVideoOptions) => Promise<Blob>;
|
|
224
334
|
invalidate: () => void;
|
|
335
|
+
/**
|
|
336
|
+
* The renderer drawing the viewer: "webgpu" only when ModelViewer's
|
|
337
|
+
* `webgpu` asked for it and the browser has WebGPU.
|
|
338
|
+
*/
|
|
339
|
+
rendererBackend: RendererBackend;
|
|
225
340
|
/**
|
|
226
341
|
* The live three.js scene, camera-controls instance, and model nodes, for
|
|
227
342
|
* integrations the rest of the API doesn't cover. Their shapes are those
|
|
@@ -257,45 +372,6 @@ type ViewerCameraProps = {
|
|
|
257
372
|
};
|
|
258
373
|
declare function useViewerCamera(options?: UseViewerCameraOptions): ViewerCameraProps;
|
|
259
374
|
|
|
260
|
-
type AnimationClipInfo = {
|
|
261
|
-
sourceName: string;
|
|
262
|
-
duration: number;
|
|
263
|
-
};
|
|
264
|
-
type AnimationPlaybackState = {
|
|
265
|
-
currentClip: string | null;
|
|
266
|
-
isPlaying: boolean;
|
|
267
|
-
speed: number;
|
|
268
|
-
time: number;
|
|
269
|
-
duration: number;
|
|
270
|
-
};
|
|
271
|
-
type AnimationControls = {
|
|
272
|
-
clips: string[];
|
|
273
|
-
clipDetails?: AnimationClipInfo[];
|
|
274
|
-
play: (clipName: string) => void;
|
|
275
|
-
pause: () => void;
|
|
276
|
-
stop: () => void;
|
|
277
|
-
setSpeed: (speed: number) => void;
|
|
278
|
-
seek?: (time: number) => void;
|
|
279
|
-
getState?: () => AnimationPlaybackState;
|
|
280
|
-
subscribe?: (listener: (state: AnimationPlaybackState) => void) => () => void;
|
|
281
|
-
};
|
|
282
|
-
type ViewerAnimationsProps = {
|
|
283
|
-
clips: string[];
|
|
284
|
-
clipDetails: AnimationClipInfo[];
|
|
285
|
-
currentClip: string | null;
|
|
286
|
-
isPlaying: boolean;
|
|
287
|
-
speed: number;
|
|
288
|
-
time: number;
|
|
289
|
-
duration: number;
|
|
290
|
-
play: (clipName: string) => void;
|
|
291
|
-
pause: () => void;
|
|
292
|
-
stop: () => void;
|
|
293
|
-
setSpeed: (speed: number) => void;
|
|
294
|
-
seek: (time: number) => void;
|
|
295
|
-
handleAnimationsReady: (controls: AnimationControls) => void;
|
|
296
|
-
};
|
|
297
|
-
declare function useViewerAnimations(): ViewerAnimationsProps;
|
|
298
|
-
|
|
299
375
|
type ObjectTransformSpace = "local" | "world";
|
|
300
376
|
|
|
301
377
|
type AnnotationMarker = SceneAnnotationMarker & {
|
|
@@ -315,7 +391,27 @@ type CustomSceneObjectsPanelProps = {
|
|
|
315
391
|
onHover?: (binding: ObjectBinding | null) => void;
|
|
316
392
|
};
|
|
317
393
|
type ModelViewerProps = GroupedModelViewerProps & {
|
|
394
|
+
/** Plain-text overrides for built-in UI labels. Missing keys use English. */
|
|
395
|
+
labels?: ModelViewerLabels;
|
|
318
396
|
modelUrl: string;
|
|
397
|
+
/**
|
|
398
|
+
* An image shown in the viewer's place until its 3D view is drawn: a render
|
|
399
|
+
* or photo of the model, best framed as the viewer frames it. Fitted inside
|
|
400
|
+
* the viewer; set the CSS variable `--ri-poster-fit: cover` to fill it.
|
|
401
|
+
*/
|
|
402
|
+
poster?: string;
|
|
403
|
+
/**
|
|
404
|
+
* `"lazy"` (default) starts the 3D view when the viewer is on or near the
|
|
405
|
+
* screen. When the page needs room for viewers in view, one scrolled away
|
|
406
|
+
* from goes back to a picture of itself, and comes back as it was. `"eager"`
|
|
407
|
+
* starts at once and keeps its view.
|
|
408
|
+
*/
|
|
409
|
+
loading?: ViewerLoading;
|
|
410
|
+
/**
|
|
411
|
+
* `"interaction"` keeps the poster, with a "View in 3D" button, until the
|
|
412
|
+
* visitor asks for the 3D view. Default `"auto"`.
|
|
413
|
+
*/
|
|
414
|
+
reveal?: ViewerReveal;
|
|
319
415
|
/** Optional 3D Tiles manifest used instead of loading `modelUrl` monolithically. */
|
|
320
416
|
tilesetUrl?: string | null;
|
|
321
417
|
/** Screen-space error target for streamed 3D Tiles. Lower is sharper. */
|
|
@@ -354,6 +450,8 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
354
450
|
* open your own menu at `clientX`/`clientY`. A right-drag still pans.
|
|
355
451
|
*/
|
|
356
452
|
onObjectContextMenu?: (event: ObjectPointerEvent) => void;
|
|
453
|
+
/** Editor preview: grab this decal and drag it over its object's surface. */
|
|
454
|
+
decalMove?: DecalMoveTarget | null;
|
|
357
455
|
/** The model finished loading: its bounds and mesh count. */
|
|
358
456
|
onModelLoaded?: (model: ViewerModelInfo) => void;
|
|
359
457
|
onLoadError?: (error: unknown) => void;
|
|
@@ -362,6 +460,10 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
362
460
|
cameraControllerType?: CameraControllerType;
|
|
363
461
|
onAction?: (event: ObjectActionEvent) => void;
|
|
364
462
|
onHiddenObjectsChange?: (next: Record<string, boolean>) => void;
|
|
463
|
+
/** Opt-in interaction analytics; no telemetry is sent by the viewer. */
|
|
464
|
+
onEngagement?: (event: ViewerEngagementEvent) => void | Promise<void>;
|
|
465
|
+
/** Log engagement events in the developer console. Default `false`. */
|
|
466
|
+
debugEngagement?: boolean;
|
|
365
467
|
/** The camera moved. Fires often while the user orbits, pans or zooms. */
|
|
366
468
|
onCameraChange?: (state: ViewerCameraState) => void;
|
|
367
469
|
onViewerReady?: (viewer: ViewerReadyState) => void;
|
|
@@ -381,6 +483,8 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
381
483
|
showDownloadButton?: boolean;
|
|
382
484
|
downloadFilename?: string;
|
|
383
485
|
showResetButton?: boolean;
|
|
486
|
+
/** Fullscreen action button; grouped form: `ui.fullscreen`. Default `false`. */
|
|
487
|
+
showFullscreenButton?: boolean;
|
|
384
488
|
showLoadingOverlay?: boolean;
|
|
385
489
|
showMouseController?: boolean;
|
|
386
490
|
mouseControllerPosition?: MouseControllerPosition;
|
|
@@ -398,10 +502,18 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
398
502
|
objectTransformSpace?: ObjectTransformSpace;
|
|
399
503
|
/** Enables canvas-focused camera shortcuts. Disabled by default. */
|
|
400
504
|
enableKeyboardNavigation?: boolean;
|
|
505
|
+
/**
|
|
506
|
+
* Cuts motion the viewer starts on its own: auto-rotate and cinematic
|
|
507
|
+
* autoplay don't start, and camera moves jump instead of gliding. `"user"`
|
|
508
|
+
* (default) follows the visitor's `prefers-reduced-motion` setting;
|
|
509
|
+
* `"always"` and `"never"` override it.
|
|
510
|
+
*/
|
|
511
|
+
reducedMotion?: ReducedMotionSetting;
|
|
401
512
|
refitOnResize?: boolean;
|
|
402
513
|
renderMode?: "always" | "demand";
|
|
403
514
|
maxDpr?: number;
|
|
404
515
|
preserveDrawingBuffer?: boolean;
|
|
516
|
+
webgpu?: boolean;
|
|
405
517
|
performanceProfile?: PerformanceProfile;
|
|
406
518
|
dracoDecoderPath?: string | false;
|
|
407
519
|
ktx2TranscoderPath?: string | false;
|
|
@@ -409,6 +521,12 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
409
521
|
showMeasureTools?: boolean;
|
|
410
522
|
showUvCheckerButton?: boolean;
|
|
411
523
|
showExplodeControls?: boolean;
|
|
524
|
+
isolation?: ViewerIsolation | null;
|
|
525
|
+
onIsolationChange?: (isolation: ViewerIsolation | null) => void;
|
|
526
|
+
showIsolateControls?: boolean;
|
|
527
|
+
showSectionTools?: boolean;
|
|
528
|
+
showMaterialVariants?: boolean;
|
|
529
|
+
showObjectNavigator?: boolean;
|
|
412
530
|
cinematic?: boolean | CinematicConfig;
|
|
413
531
|
measurementUnit?: string;
|
|
414
532
|
enableXR?: boolean;
|
|
@@ -417,6 +535,9 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
417
535
|
mobileHandoffUrl?: string;
|
|
418
536
|
showAnnotationNavigation?: boolean;
|
|
419
537
|
showAnnotationOnHover?: boolean;
|
|
538
|
+
showAnnotationFilters?: boolean;
|
|
539
|
+
annotationCategories?: string[] | null;
|
|
540
|
+
onAnnotationCategoriesChange?: (categories: string[] | null) => void;
|
|
420
541
|
onSceneConfigChange?: (config: SceneConfig) => void;
|
|
421
542
|
showViewGizmo?: boolean;
|
|
422
543
|
/**
|
|
@@ -445,4 +566,4 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
445
566
|
texturePositioning?: boolean | TexturePositioningControls;
|
|
446
567
|
};
|
|
447
568
|
|
|
448
|
-
export { type
|
|
569
|
+
export { type AnnotationMarker as A, type CameraControllerType as C, type DecalMoveTarget as D, type GroupedModelViewerProps as G, type HomeCameraState as H, MODEL_VIEWER_PRESETS as M, type ObjectTransformSpace as O, type PerformanceProfile as P, type TexturePositioningControls as T, type UseViewerCameraOptions as U, type ViewerCameraPreset as V, type XRScaleMode as X, type CameraLimits as a, type CaptureImageOptions as b, type CaptureVideoOptions as c, type CinematicConfig as d, type CinematicWaypoint as e, type CustomObjectBindingDataPanelProps as f, type CustomSceneObjectsPanelProps as g, type ModelViewerControlsOptions as h, type ModelViewerDecoderOptions as i, type ModelViewerPerfOptions as j, type ModelViewerPreset as k, type ModelViewerProps as l, type ModelViewerTilesOptions as m, type ModelViewerToolsOptions as n, type ModelViewerUiOptions as o, type ModelViewerXrOptions as p, type MouseControllerPosition as q, type ViewerCameraProps as r, type ViewerEngagementEvent as s, type ViewerReadyState as t, useViewerCamera as u };
|
|
@@ -1,9 +1,57 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { M as ModelFormat,
|
|
2
|
+
import { R as ReducedMotionSetting, c as ModelViewerLabels } from './materialVariants-DnZe9eMC.mjs';
|
|
3
|
+
import { V as ViewerLoading, c as ViewerReveal, M as ModelFormat, b as ViewerModelInfo } from './modelInfo-BYebMPdZ.mjs';
|
|
4
|
+
import { r as ObjectBindingDecal, Q as ObjectSurfacePoint, o as ObjectBinding, S as RendererBackend, ap as ViewerCameraState, Y as SceneAnnotationMarker, ar as ViewerObjectInfo, P as ObjectPointerEvent, n as ObjectActionEvent, e as AnimationControls, ao as ViewerCameraConfig, a1 as SceneConfig, aq as ViewerIsolation } from './rendererBackend-QwMzISTn.mjs';
|
|
4
5
|
import { CameraControls } from '@react-three/drei';
|
|
5
6
|
import { Object3D } from 'three';
|
|
6
7
|
|
|
8
|
+
/** Engagement from deliberate viewer interactions, with model/session context. */
|
|
9
|
+
type ViewerEngagementEvent = {
|
|
10
|
+
/** Ephemeral identifier for this viewer/model session; no persistent storage. */
|
|
11
|
+
sessionId: string;
|
|
12
|
+
/** ISO timestamp of the event. */
|
|
13
|
+
timestamp: string;
|
|
14
|
+
/** Milliseconds since tracking started for this model. */
|
|
15
|
+
elapsedMs: number;
|
|
16
|
+
modelUrl: string;
|
|
17
|
+
tilesetUrl: string | null;
|
|
18
|
+
} & ({
|
|
19
|
+
type: "part-viewed";
|
|
20
|
+
objectId: string;
|
|
21
|
+
objectKey: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
source: "canvas" | "panel" | "keyboard";
|
|
24
|
+
} | {
|
|
25
|
+
type: "variant-chosen";
|
|
26
|
+
/** The variant chosen; null when a group's choice was cleared. */
|
|
27
|
+
variant: string | null;
|
|
28
|
+
/** The group's previous choice. */
|
|
29
|
+
previousVariant: string | null;
|
|
30
|
+
/** The option group's name; null for a group without one. */
|
|
31
|
+
group: string | null;
|
|
32
|
+
} | {
|
|
33
|
+
type: "ar-started";
|
|
34
|
+
} | {
|
|
35
|
+
type: "ar-ended";
|
|
36
|
+
durationMs: number;
|
|
37
|
+
reason: "session-ended" | "interrupted";
|
|
38
|
+
} | {
|
|
39
|
+
type: "ar-launch-requested";
|
|
40
|
+
channel: "quick-look" | "mobile-handoff";
|
|
41
|
+
} | {
|
|
42
|
+
type: "tour-started";
|
|
43
|
+
annotationCount: number;
|
|
44
|
+
} | {
|
|
45
|
+
type: "tour-completed";
|
|
46
|
+
annotationCount: number;
|
|
47
|
+
durationMs: number;
|
|
48
|
+
} | {
|
|
49
|
+
type: "tour-stopped";
|
|
50
|
+
annotationCount: number;
|
|
51
|
+
durationMs: number;
|
|
52
|
+
reason: "stopped" | "restarted" | "annotations-changed" | "interrupted";
|
|
53
|
+
});
|
|
54
|
+
|
|
7
55
|
type CameraLimits = {
|
|
8
56
|
/** Closest the camera can get to its target, in scene units. Default 0. */
|
|
9
57
|
minDistance?: number;
|
|
@@ -49,6 +97,8 @@ type ModelViewerUiOptions = {
|
|
|
49
97
|
download?: boolean | string;
|
|
50
98
|
/** The reset-view button. Default `true`. */
|
|
51
99
|
reset?: boolean;
|
|
100
|
+
/** The viewer fullscreen toggle in the action bar. Default `false`. */
|
|
101
|
+
fullscreen?: boolean;
|
|
52
102
|
/** The loading overlay and load-error message. Default `true`. */
|
|
53
103
|
loadingOverlay?: boolean;
|
|
54
104
|
/** The axis gizmo in the top-right corner. Default `false`. */
|
|
@@ -62,8 +112,17 @@ type ModelViewerUiOptions = {
|
|
|
62
112
|
annotationNavigation?: boolean;
|
|
63
113
|
/** Show an annotation's details when its marker is hovered. Default `false`. */
|
|
64
114
|
annotationOnHover?: boolean;
|
|
115
|
+
/** Category filter chips. Default `true` when annotations have categories. */
|
|
116
|
+
annotationFilters?: boolean;
|
|
65
117
|
/** Highlight objects under the pointer. Default `true`. */
|
|
66
118
|
highlightOnHover?: boolean;
|
|
119
|
+
/** Swatch rows for the model's glTF material variants, one per option group. Default `true`. */
|
|
120
|
+
materialVariants?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* A tab stop for moving through and selecting objects with the keyboard,
|
|
123
|
+
* shown only while it has focus. Default `true`.
|
|
124
|
+
*/
|
|
125
|
+
objectNavigator?: boolean;
|
|
67
126
|
};
|
|
68
127
|
/**
|
|
69
128
|
* Takes over parts of texture positioning (`texturePositioning`). Fields left
|
|
@@ -92,6 +151,10 @@ type ModelViewerToolsOptions = {
|
|
|
92
151
|
uvChecker?: boolean;
|
|
93
152
|
/** The exploded-view slider. Default `false`. */
|
|
94
153
|
explode?: boolean;
|
|
154
|
+
/** The section-cut tool, to cut the model open along an axis. Default `false`. */
|
|
155
|
+
section?: boolean;
|
|
156
|
+
/** Isolate buttons in the scene objects panel, and a "Show all" pill. Default `false`. */
|
|
157
|
+
isolate?: boolean;
|
|
95
158
|
/** Texture offset, rotation and Move/Zoom for textured objects. Default `false`. */
|
|
96
159
|
texturePositioning?: boolean | TexturePositioningControls;
|
|
97
160
|
};
|
|
@@ -100,13 +163,19 @@ type ModelViewerControlsOptions = {
|
|
|
100
163
|
enabled?: boolean;
|
|
101
164
|
/** Move the camera with the keyboard while the canvas has focus. Default `false`. */
|
|
102
165
|
keyboard?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Cut motion the viewer starts on its own (auto-rotate, cinematic autoplay,
|
|
168
|
+
* camera glides). `"user"` follows the visitor's reduced-motion setting.
|
|
169
|
+
* Default `"user"`.
|
|
170
|
+
*/
|
|
171
|
+
reducedMotion?: ReducedMotionSetting;
|
|
103
172
|
/** Allow zooming. Default `true`. */
|
|
104
173
|
zoom?: boolean;
|
|
105
174
|
/** Zoom to an object when it's selected. Default `true`. */
|
|
106
175
|
zoomOnSelect?: boolean;
|
|
107
176
|
/** Turn the model slowly; a number sets the speed (1 is normal). Default `false`. */
|
|
108
177
|
autoRotate?: boolean | number;
|
|
109
|
-
/** Re-frame the model when the viewer is resized. Default `true`. */
|
|
178
|
+
/** Re-frame the model, or the selected object it zoomed to, when the viewer is resized. Default `true`. */
|
|
110
179
|
refitOnResize?: boolean;
|
|
111
180
|
/** Distance, angle and pan limits for the camera. */
|
|
112
181
|
limits?: CameraLimits;
|
|
@@ -124,6 +193,12 @@ type ModelViewerPerfOptions = {
|
|
|
124
193
|
profile?: PerformanceProfile;
|
|
125
194
|
/** Needed for Download PNG and captureImage; costs GPU time. Default `false`. */
|
|
126
195
|
preserveDrawingBuffer?: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Draw with three's WebGPU renderer where the browser has WebGPU, WebGL
|
|
198
|
+
* elsewhere. Leaves out post-processing effects, contact shadows and WebXR.
|
|
199
|
+
* Default `false`.
|
|
200
|
+
*/
|
|
201
|
+
webgpu?: boolean;
|
|
127
202
|
};
|
|
128
203
|
type ModelViewerTilesOptions = {
|
|
129
204
|
/** A 3D Tiles `tileset.json` to stream instead of loading `modelUrl` whole. */
|
|
@@ -168,6 +243,13 @@ type GroupedModelViewerProps = {
|
|
|
168
243
|
/** What each preset sets. Props that aren't listed keep their defaults. */
|
|
169
244
|
declare const MODEL_VIEWER_PRESETS: Readonly<Record<ModelViewerPreset, Readonly<Partial<ModelViewerProps>>>>;
|
|
170
245
|
|
|
246
|
+
type DecalMoveTarget = {
|
|
247
|
+
objectId: string;
|
|
248
|
+
decal: ObjectBindingDecal;
|
|
249
|
+
onCommit: (surface: ObjectSurfacePoint) => void;
|
|
250
|
+
onCancel: () => void;
|
|
251
|
+
};
|
|
252
|
+
|
|
171
253
|
type CameraControllerType = "orbit" | "pointerLock";
|
|
172
254
|
|
|
173
255
|
type CinematicWaypoint = {
|
|
@@ -195,6 +277,32 @@ type CaptureImageOptions = {
|
|
|
195
277
|
transparent?: boolean;
|
|
196
278
|
};
|
|
197
279
|
|
|
280
|
+
type CaptureVideoOptions = {
|
|
281
|
+
/** Defaults to cinematic when a path is enabled, otherwise turntable. */
|
|
282
|
+
mode?: "cinematic" | "turntable";
|
|
283
|
+
/**
|
|
284
|
+
* Auto prefers WebM, then MP4. `"gif"` makes an animated GIF that loops
|
|
285
|
+
* forever. Explicit formats reject if unsupported.
|
|
286
|
+
*/
|
|
287
|
+
format?: "auto" | "webm" | "mp4" | "gif";
|
|
288
|
+
/**
|
|
289
|
+
* Seconds per pass, in (0, 300]. Defaults to path timing, or an orbit of
|
|
290
|
+
* 24s (8s for a GIF).
|
|
291
|
+
*/
|
|
292
|
+
duration?: number;
|
|
293
|
+
/** Capture frame rate, from 1 to 60. Default 30 (15 for a GIF). */
|
|
294
|
+
fps?: number;
|
|
295
|
+
/** Encoder target bitrate in bits per second. Default 8,000,000. Not used for GIFs. */
|
|
296
|
+
videoBitsPerSecond?: number;
|
|
297
|
+
/**
|
|
298
|
+
* GIF width in pixels, from 16 to 4096; the height follows the canvas. Never
|
|
299
|
+
* wider than the canvas. Default 480.
|
|
300
|
+
*/
|
|
301
|
+
gifWidth?: number;
|
|
302
|
+
/** Aborting discards the recording and restores the viewer. */
|
|
303
|
+
signal?: AbortSignal;
|
|
304
|
+
};
|
|
305
|
+
|
|
198
306
|
type ViewerCameraPreset = {
|
|
199
307
|
position: [number, number, number];
|
|
200
308
|
target: [number, number, number];
|
|
@@ -221,7 +329,14 @@ type ViewerReadyState = {
|
|
|
221
329
|
objectBindings: Record<string, ObjectBinding>;
|
|
222
330
|
homeCameraState: HomeCameraState | null;
|
|
223
331
|
captureImage: (options?: CaptureImageOptions) => Promise<string>;
|
|
332
|
+
/** Records one cinematic pass or turntable revolution as a video Blob. */
|
|
333
|
+
captureVideo: (options?: CaptureVideoOptions) => Promise<Blob>;
|
|
224
334
|
invalidate: () => void;
|
|
335
|
+
/**
|
|
336
|
+
* The renderer drawing the viewer: "webgpu" only when ModelViewer's
|
|
337
|
+
* `webgpu` asked for it and the browser has WebGPU.
|
|
338
|
+
*/
|
|
339
|
+
rendererBackend: RendererBackend;
|
|
225
340
|
/**
|
|
226
341
|
* The live three.js scene, camera-controls instance, and model nodes, for
|
|
227
342
|
* integrations the rest of the API doesn't cover. Their shapes are those
|
|
@@ -257,45 +372,6 @@ type ViewerCameraProps = {
|
|
|
257
372
|
};
|
|
258
373
|
declare function useViewerCamera(options?: UseViewerCameraOptions): ViewerCameraProps;
|
|
259
374
|
|
|
260
|
-
type AnimationClipInfo = {
|
|
261
|
-
sourceName: string;
|
|
262
|
-
duration: number;
|
|
263
|
-
};
|
|
264
|
-
type AnimationPlaybackState = {
|
|
265
|
-
currentClip: string | null;
|
|
266
|
-
isPlaying: boolean;
|
|
267
|
-
speed: number;
|
|
268
|
-
time: number;
|
|
269
|
-
duration: number;
|
|
270
|
-
};
|
|
271
|
-
type AnimationControls = {
|
|
272
|
-
clips: string[];
|
|
273
|
-
clipDetails?: AnimationClipInfo[];
|
|
274
|
-
play: (clipName: string) => void;
|
|
275
|
-
pause: () => void;
|
|
276
|
-
stop: () => void;
|
|
277
|
-
setSpeed: (speed: number) => void;
|
|
278
|
-
seek?: (time: number) => void;
|
|
279
|
-
getState?: () => AnimationPlaybackState;
|
|
280
|
-
subscribe?: (listener: (state: AnimationPlaybackState) => void) => () => void;
|
|
281
|
-
};
|
|
282
|
-
type ViewerAnimationsProps = {
|
|
283
|
-
clips: string[];
|
|
284
|
-
clipDetails: AnimationClipInfo[];
|
|
285
|
-
currentClip: string | null;
|
|
286
|
-
isPlaying: boolean;
|
|
287
|
-
speed: number;
|
|
288
|
-
time: number;
|
|
289
|
-
duration: number;
|
|
290
|
-
play: (clipName: string) => void;
|
|
291
|
-
pause: () => void;
|
|
292
|
-
stop: () => void;
|
|
293
|
-
setSpeed: (speed: number) => void;
|
|
294
|
-
seek: (time: number) => void;
|
|
295
|
-
handleAnimationsReady: (controls: AnimationControls) => void;
|
|
296
|
-
};
|
|
297
|
-
declare function useViewerAnimations(): ViewerAnimationsProps;
|
|
298
|
-
|
|
299
375
|
type ObjectTransformSpace = "local" | "world";
|
|
300
376
|
|
|
301
377
|
type AnnotationMarker = SceneAnnotationMarker & {
|
|
@@ -315,7 +391,27 @@ type CustomSceneObjectsPanelProps = {
|
|
|
315
391
|
onHover?: (binding: ObjectBinding | null) => void;
|
|
316
392
|
};
|
|
317
393
|
type ModelViewerProps = GroupedModelViewerProps & {
|
|
394
|
+
/** Plain-text overrides for built-in UI labels. Missing keys use English. */
|
|
395
|
+
labels?: ModelViewerLabels;
|
|
318
396
|
modelUrl: string;
|
|
397
|
+
/**
|
|
398
|
+
* An image shown in the viewer's place until its 3D view is drawn: a render
|
|
399
|
+
* or photo of the model, best framed as the viewer frames it. Fitted inside
|
|
400
|
+
* the viewer; set the CSS variable `--ri-poster-fit: cover` to fill it.
|
|
401
|
+
*/
|
|
402
|
+
poster?: string;
|
|
403
|
+
/**
|
|
404
|
+
* `"lazy"` (default) starts the 3D view when the viewer is on or near the
|
|
405
|
+
* screen. When the page needs room for viewers in view, one scrolled away
|
|
406
|
+
* from goes back to a picture of itself, and comes back as it was. `"eager"`
|
|
407
|
+
* starts at once and keeps its view.
|
|
408
|
+
*/
|
|
409
|
+
loading?: ViewerLoading;
|
|
410
|
+
/**
|
|
411
|
+
* `"interaction"` keeps the poster, with a "View in 3D" button, until the
|
|
412
|
+
* visitor asks for the 3D view. Default `"auto"`.
|
|
413
|
+
*/
|
|
414
|
+
reveal?: ViewerReveal;
|
|
319
415
|
/** Optional 3D Tiles manifest used instead of loading `modelUrl` monolithically. */
|
|
320
416
|
tilesetUrl?: string | null;
|
|
321
417
|
/** Screen-space error target for streamed 3D Tiles. Lower is sharper. */
|
|
@@ -354,6 +450,8 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
354
450
|
* open your own menu at `clientX`/`clientY`. A right-drag still pans.
|
|
355
451
|
*/
|
|
356
452
|
onObjectContextMenu?: (event: ObjectPointerEvent) => void;
|
|
453
|
+
/** Editor preview: grab this decal and drag it over its object's surface. */
|
|
454
|
+
decalMove?: DecalMoveTarget | null;
|
|
357
455
|
/** The model finished loading: its bounds and mesh count. */
|
|
358
456
|
onModelLoaded?: (model: ViewerModelInfo) => void;
|
|
359
457
|
onLoadError?: (error: unknown) => void;
|
|
@@ -362,6 +460,10 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
362
460
|
cameraControllerType?: CameraControllerType;
|
|
363
461
|
onAction?: (event: ObjectActionEvent) => void;
|
|
364
462
|
onHiddenObjectsChange?: (next: Record<string, boolean>) => void;
|
|
463
|
+
/** Opt-in interaction analytics; no telemetry is sent by the viewer. */
|
|
464
|
+
onEngagement?: (event: ViewerEngagementEvent) => void | Promise<void>;
|
|
465
|
+
/** Log engagement events in the developer console. Default `false`. */
|
|
466
|
+
debugEngagement?: boolean;
|
|
365
467
|
/** The camera moved. Fires often while the user orbits, pans or zooms. */
|
|
366
468
|
onCameraChange?: (state: ViewerCameraState) => void;
|
|
367
469
|
onViewerReady?: (viewer: ViewerReadyState) => void;
|
|
@@ -381,6 +483,8 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
381
483
|
showDownloadButton?: boolean;
|
|
382
484
|
downloadFilename?: string;
|
|
383
485
|
showResetButton?: boolean;
|
|
486
|
+
/** Fullscreen action button; grouped form: `ui.fullscreen`. Default `false`. */
|
|
487
|
+
showFullscreenButton?: boolean;
|
|
384
488
|
showLoadingOverlay?: boolean;
|
|
385
489
|
showMouseController?: boolean;
|
|
386
490
|
mouseControllerPosition?: MouseControllerPosition;
|
|
@@ -398,10 +502,18 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
398
502
|
objectTransformSpace?: ObjectTransformSpace;
|
|
399
503
|
/** Enables canvas-focused camera shortcuts. Disabled by default. */
|
|
400
504
|
enableKeyboardNavigation?: boolean;
|
|
505
|
+
/**
|
|
506
|
+
* Cuts motion the viewer starts on its own: auto-rotate and cinematic
|
|
507
|
+
* autoplay don't start, and camera moves jump instead of gliding. `"user"`
|
|
508
|
+
* (default) follows the visitor's `prefers-reduced-motion` setting;
|
|
509
|
+
* `"always"` and `"never"` override it.
|
|
510
|
+
*/
|
|
511
|
+
reducedMotion?: ReducedMotionSetting;
|
|
401
512
|
refitOnResize?: boolean;
|
|
402
513
|
renderMode?: "always" | "demand";
|
|
403
514
|
maxDpr?: number;
|
|
404
515
|
preserveDrawingBuffer?: boolean;
|
|
516
|
+
webgpu?: boolean;
|
|
405
517
|
performanceProfile?: PerformanceProfile;
|
|
406
518
|
dracoDecoderPath?: string | false;
|
|
407
519
|
ktx2TranscoderPath?: string | false;
|
|
@@ -409,6 +521,12 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
409
521
|
showMeasureTools?: boolean;
|
|
410
522
|
showUvCheckerButton?: boolean;
|
|
411
523
|
showExplodeControls?: boolean;
|
|
524
|
+
isolation?: ViewerIsolation | null;
|
|
525
|
+
onIsolationChange?: (isolation: ViewerIsolation | null) => void;
|
|
526
|
+
showIsolateControls?: boolean;
|
|
527
|
+
showSectionTools?: boolean;
|
|
528
|
+
showMaterialVariants?: boolean;
|
|
529
|
+
showObjectNavigator?: boolean;
|
|
412
530
|
cinematic?: boolean | CinematicConfig;
|
|
413
531
|
measurementUnit?: string;
|
|
414
532
|
enableXR?: boolean;
|
|
@@ -417,6 +535,9 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
417
535
|
mobileHandoffUrl?: string;
|
|
418
536
|
showAnnotationNavigation?: boolean;
|
|
419
537
|
showAnnotationOnHover?: boolean;
|
|
538
|
+
showAnnotationFilters?: boolean;
|
|
539
|
+
annotationCategories?: string[] | null;
|
|
540
|
+
onAnnotationCategoriesChange?: (categories: string[] | null) => void;
|
|
420
541
|
onSceneConfigChange?: (config: SceneConfig) => void;
|
|
421
542
|
showViewGizmo?: boolean;
|
|
422
543
|
/**
|
|
@@ -445,4 +566,4 @@ type ModelViewerProps = GroupedModelViewerProps & {
|
|
|
445
566
|
texturePositioning?: boolean | TexturePositioningControls;
|
|
446
567
|
};
|
|
447
568
|
|
|
448
|
-
export { type
|
|
569
|
+
export { type AnnotationMarker as A, type CameraControllerType as C, type DecalMoveTarget as D, type GroupedModelViewerProps as G, type HomeCameraState as H, MODEL_VIEWER_PRESETS as M, type ObjectTransformSpace as O, type PerformanceProfile as P, type TexturePositioningControls as T, type UseViewerCameraOptions as U, type ViewerCameraPreset as V, type XRScaleMode as X, type CameraLimits as a, type CaptureImageOptions as b, type CaptureVideoOptions as c, type CinematicConfig as d, type CinematicWaypoint as e, type CustomObjectBindingDataPanelProps as f, type CustomSceneObjectsPanelProps as g, type ModelViewerControlsOptions as h, type ModelViewerDecoderOptions as i, type ModelViewerPerfOptions as j, type ModelViewerPreset as k, type ModelViewerProps as l, type ModelViewerTilesOptions as m, type ModelViewerToolsOptions as n, type ModelViewerUiOptions as o, type ModelViewerXrOptions as p, type MouseControllerPosition as q, type ViewerCameraProps as r, type ViewerEngagementEvent as s, type ViewerReadyState as t, useViewerCamera as u };
|