@liveroom-tech/react-immersive 1.3.5 → 2.0.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 +103 -59
- package/dist/index.d.mts +49 -8
- package/dist/index.d.ts +49 -8
- package/dist/index.js +576 -331
- package/dist/index.mjs +587 -342
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,11 +9,13 @@ The library currently exports:
|
|
|
9
9
|
```ts
|
|
10
10
|
import {
|
|
11
11
|
BindingBuilder,
|
|
12
|
+
material,
|
|
12
13
|
ModelViewer,
|
|
14
|
+
patchBindings,
|
|
13
15
|
SimpleModelViewer,
|
|
14
16
|
useObjectBinding,
|
|
15
17
|
useObjectBindingIds,
|
|
16
|
-
|
|
18
|
+
useObjectBindings,
|
|
17
19
|
useViewerActions,
|
|
18
20
|
useViewerAnimations,
|
|
19
21
|
useViewerCamera,
|
|
@@ -25,13 +27,13 @@ import {
|
|
|
25
27
|
} from "@liveroom-tech/react-immersive";
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
It also exports types for `ObjectBinding`, `ObjectBindingMaterial`, `ObjectActionEvent`, `SceneConfig`, `AnimationControls`, `CinematicConfig` / `CinematicWaypoint`, and related shapes used throughout this document.
|
|
30
|
+
It also exports types for `ObjectBinding`, `ObjectBindingMaterial`, `ObjectBindingsController`, `ObjectActionEvent`, `SceneConfig`, `AnimationControls`, `CinematicConfig` / `CinematicWaypoint`, and related shapes used throughout this document.
|
|
29
31
|
|
|
30
32
|
`ModelViewer` provides:
|
|
31
33
|
|
|
32
34
|
- GLB/GLTF model rendering through `@react-three/fiber` and `@react-three/drei`
|
|
33
35
|
- orbit/pan/zoom camera controls via `CameraControls`
|
|
34
|
-
- auto-fits the model on load, and re-fits when the canvas is resized (window resize, device rotation, or a panel opening/closing)
|
|
36
|
+
- auto-fits the model on load, and re-fits when the canvas is resized (window resize, device rotation, or a panel opening/closing), toggleable through `refitOnResize` to instead preserve the user's orbit/zoom
|
|
35
37
|
- optional custom scene lighting through a `lights` prop
|
|
36
38
|
- optional custom camera configuration through a `camera` prop
|
|
37
39
|
- optional custom background color through a `backgroundColor` prop
|
|
@@ -41,11 +43,13 @@ It also exports types for `ObjectBinding`, `ObjectBindingMaterial`, `ObjectActio
|
|
|
41
43
|
- optional custom right scene objects panel through `customSceneObjectsPanel`
|
|
42
44
|
- optional hiding of either built-in panel through `showObjectBindingDataPanel` and `showSceneObjectsPanel`
|
|
43
45
|
- optional model export button through `showDownloadButton` and `downloadFilename`, plus an independent `showResetButton` toggle for the rest of that action bar
|
|
46
|
+
- an optional UV Checker toolbar button through `showUvCheckerButton`, for inspecting UV scale, stretching, seams, orientation, and missing UV0 coordinates directly in `ModelViewer`
|
|
44
47
|
- click-to-measure distance tool and a bounding-box dimensions overlay through `showMeasureTools` and `measurementUnit`
|
|
45
48
|
- an exploded-view slider that slides each bound part outward from the model center to reveal interior/assembly structure through `showExplodeControls`
|
|
46
|
-
- a cinematic auto-camera that glides the camera along authored waypoints (or a zero-config showcase orbit), like a film, through `cinematic
|
|
49
|
+
- a cinematic auto-camera that glides the camera along authored waypoints (or a zero-config showcase orbit), like a film, through `cinematic`, with a play/pause control that yields the moment you touch the camera
|
|
47
50
|
- a guided-tour control cluster (Previous/Stop/Next) for stepping through annotations, toggleable via `showAnnotationNavigation`
|
|
48
51
|
- optional annotation detail popups on marker hover via `showAnnotationOnHover`
|
|
52
|
+
- PBR, Matcap, and UV Checker renderer modes, with the checker exposing UV stretching, seams, rotation, and missing UV0 data directly on the model
|
|
49
53
|
- a `sceneConfig` prop accepting the same scene-wide config (lighting, environment, background, post-processing, animations, annotations) authored by `BindingBuilder`'s Scene tab
|
|
50
54
|
- render-loop and perf tuning through `renderMode`, `maxDpr`, `performanceProfile`, and compressed-asset decoder options (`dracoDecoderPath`, `ktx2TranscoderPath`, `meshopt`)
|
|
51
55
|
- WebXR "View in your space" (AR) and "Enter VR" through `enableXR`, with tap-to-place, pinch-to-resize, and twist-to-rotate AR placement gestures
|
|
@@ -75,10 +79,10 @@ It also exports types for `ObjectBinding`, `ObjectBindingMaterial`, `ObjectActio
|
|
|
75
79
|
- a one-click material preset gallery (wood, metal, chrome, glass, plastic, fabric, ceramic, concrete, etc.)
|
|
76
80
|
- undo/redo for both the Object tab's bindings and the Scene tab's config, independently, with `Cmd/Ctrl+Z` / `Cmd/Ctrl+Shift+Z` shortcuts
|
|
77
81
|
- a Scene tab for the same `sceneConfig` shape `ModelViewer` accepts (lighting, environment, background, post-processing, animations, annotations, and cinematic camera paths)
|
|
78
|
-
- a Cinematic sub-tab for authoring a camera path visually
|
|
82
|
+
- a Cinematic sub-tab for authoring a camera path visually, frame the model, capture the current view as a waypoint, reorder/preview/delete waypoints, and toggle loop/auto-play; stored on `sceneConfig.cinematic` and replayed by `ModelViewer`'s `cinematic` prop
|
|
79
83
|
- import a previously exported `objectBindings.json` or `sceneConfig.json` and merge it back onto the current model/config
|
|
80
84
|
- live preview using `ModelViewer`
|
|
81
|
-
- export as JSON or TypeScript
|
|
85
|
+
- export as JSON or TypeScript, bundled into a `.zip` with a `materials/` folder automatically when any texture field was filled by file upload, otherwise a plain file
|
|
82
86
|
- license-tier gating for some editor features (texture maps, environment lighting/backgrounds, wireframe preview, animation configuration, annotations, post-processing)
|
|
83
87
|
|
|
84
88
|
`SimpleModelViewer` provides:
|
|
@@ -160,36 +164,36 @@ Peer dependencies:
|
|
|
160
164
|
- `react >= 17`
|
|
161
165
|
- `react-dom >= 17`
|
|
162
166
|
|
|
163
|
-
`ModelViewer` and `BindingBuilder` require a `licenseKey` at runtime (see [`licenseKey`](#licensekey)). Get one from the Developer Portal
|
|
167
|
+
`ModelViewer` and `BindingBuilder` require a `licenseKey` at runtime (see [`licenseKey`](#licensekey)). Get one from the Developer Portal, see [Resources](#resources) below.
|
|
164
168
|
|
|
165
169
|
## Resources
|
|
166
170
|
|
|
167
|
-
- [Developer Portal](https://react-immersive.liveroom.dev)
|
|
168
|
-
- [Docs](https://react-immersive.liveroom.dev/docs)
|
|
169
|
-
- [Examples & community repo](https://github.com/liveroom-technologies/react-immersive)
|
|
170
|
-
- [Report a bug / request a feature](https://github.com/liveroom-technologies/react-immersive-docs/issues)
|
|
171
|
-
- [Discussions & Q&A](https://github.com/liveroom-technologies/react-immersive-docs/discussions)
|
|
172
|
-
- [Private support / security](mailto:developers@liveroom.xyz?subject=React%20Immersive%20Support)
|
|
173
|
-
- [Live editor](https://react-immersive.liveroom.dev/editor)
|
|
171
|
+
- [Developer Portal](https://react-immersive.liveroom.dev), sign in, pick a plan, and generate a `licenseKey`
|
|
172
|
+
- [Docs](https://react-immersive.liveroom.dev/docs), full reference for every component, hook, and prop
|
|
173
|
+
- [Examples & community repo](https://github.com/liveroom-technologies/react-immersive), public docs source, starter examples, and community resources
|
|
174
|
+
- [Report a bug / request a feature](https://github.com/liveroom-technologies/react-immersive-docs/issues), for public bug reports, docs issues, and feature requests
|
|
175
|
+
- [Discussions & Q&A](https://github.com/liveroom-technologies/react-immersive-docs/discussions), ask questions, share ideas, and compare approaches
|
|
176
|
+
- [Private support / security](mailto:developers@liveroom.xyz?subject=React%20Immersive%20Support), for license, account, confidential customer, or security-sensitive issues
|
|
177
|
+
- [Live editor](https://react-immersive.liveroom.dev/editor), try `BindingBuilder` in the browser without installing anything
|
|
174
178
|
- [npm package](https://www.npmjs.com/package/@liveroom-tech/react-immersive)
|
|
175
179
|
|
|
176
180
|
## Quick Start
|
|
177
181
|
|
|
178
182
|
```tsx
|
|
179
|
-
import { useState } from "react";
|
|
180
183
|
import {
|
|
181
184
|
ModelViewer,
|
|
182
185
|
useObjectBinding,
|
|
183
|
-
|
|
186
|
+
useObjectBindings,
|
|
184
187
|
useViewerActions,
|
|
185
188
|
useViewerAnimations,
|
|
186
189
|
useViewerCamera,
|
|
187
190
|
useViewerHover,
|
|
188
191
|
useViewerModel,
|
|
189
192
|
useViewerSelection,
|
|
193
|
+
type ObjectBinding,
|
|
190
194
|
} from "@liveroom-tech/react-immersive";
|
|
191
195
|
|
|
192
|
-
const initialBindings = {
|
|
196
|
+
const initialBindings: Record<string, ObjectBinding> = {
|
|
193
197
|
CarBody: {
|
|
194
198
|
id: "car-body",
|
|
195
199
|
modelObjectId: "CarBody",
|
|
@@ -218,7 +222,12 @@ const initialBindings = {
|
|
|
218
222
|
};
|
|
219
223
|
|
|
220
224
|
export default function Example() {
|
|
221
|
-
const
|
|
225
|
+
const {
|
|
226
|
+
objectBindings,
|
|
227
|
+
setObjectBindings,
|
|
228
|
+
hiddenObjects,
|
|
229
|
+
toggleObjectVisibility,
|
|
230
|
+
} = useObjectBindings(initialBindings);
|
|
222
231
|
const { selectedObjectBinding, handleObjectSelect } = useViewerSelection();
|
|
223
232
|
const { hoveredObjectBinding, handleHoveredObject } = useViewerHover();
|
|
224
233
|
const {
|
|
@@ -239,10 +248,6 @@ export default function Example() {
|
|
|
239
248
|
handleModelLoaded,
|
|
240
249
|
handleLoadError,
|
|
241
250
|
} = useViewerModel();
|
|
242
|
-
const { hiddenObjects, toggleObjectVisibility } = useObjectVisibility(
|
|
243
|
-
objectBindings,
|
|
244
|
-
setObjectBindings,
|
|
245
|
-
);
|
|
246
251
|
const { getActionsForObject, runAction } = useViewerActions(objectBindings, {
|
|
247
252
|
onAction: (event) => {},
|
|
248
253
|
onObjectBindingsChange: setObjectBindings,
|
|
@@ -323,12 +328,17 @@ const ids = useObjectBindingIds(objectBindings);
|
|
|
323
328
|
// → ["CarBody", "WheelFL", "WheelFR", ...]
|
|
324
329
|
```
|
|
325
330
|
|
|
326
|
-
If you want
|
|
331
|
+
If you want one state owner for binding patches, materials, and visibility, use `useObjectBindings`:
|
|
327
332
|
|
|
328
333
|
```tsx
|
|
329
|
-
const [objectBindings, setObjectBindings] = useState(initialBindings);
|
|
330
|
-
|
|
331
334
|
const {
|
|
335
|
+
objectBindings,
|
|
336
|
+
setObjectBindings,
|
|
337
|
+
patch,
|
|
338
|
+
setMaterial,
|
|
339
|
+
setBaseColor,
|
|
340
|
+
resetMaterial,
|
|
341
|
+
getMaterial,
|
|
332
342
|
hiddenObjects,
|
|
333
343
|
hiddenObjectIds,
|
|
334
344
|
hideObject,
|
|
@@ -336,7 +346,7 @@ const {
|
|
|
336
346
|
toggleObjectVisibility,
|
|
337
347
|
isObjectHidden,
|
|
338
348
|
clearHiddenObjects,
|
|
339
|
-
} =
|
|
349
|
+
} = useObjectBindings(initialBindings);
|
|
340
350
|
|
|
341
351
|
<ModelViewer
|
|
342
352
|
modelUrl="/model.glb"
|
|
@@ -346,16 +356,19 @@ const {
|
|
|
346
356
|
/>;
|
|
347
357
|
```
|
|
348
358
|
|
|
349
|
-
`
|
|
359
|
+
`useObjectBindings` owns the state used by the viewer. Every setter uses a functional update, so consecutive material, visibility, and general patch calls in the same tick compose instead of overwriting each other.
|
|
350
360
|
|
|
351
|
-
|
|
361
|
+
Object identifiers accepted by its methods can be:
|
|
352
362
|
|
|
353
363
|
- the object binding map key
|
|
354
364
|
- `binding.id`
|
|
355
365
|
- `binding.modelObjectId`
|
|
356
366
|
|
|
357
|
-
|
|
367
|
+
The hook returns:
|
|
358
368
|
|
|
369
|
+
- `objectBindings` and `setObjectBindings`
|
|
370
|
+
- `patch` for any binding field or atomic edit batch
|
|
371
|
+
- `setMaterial`, `setBaseColor`, `resetMaterial`, and `getMaterial`
|
|
359
372
|
- `hiddenObjects`: a derived map of hidden binding keys
|
|
360
373
|
- `hiddenObjectIds`: the currently hidden binding IDs
|
|
361
374
|
- `hideObject`, `showObject`, `toggleObjectVisibility`
|
|
@@ -458,7 +471,7 @@ type BindingBuilderProps = {
|
|
|
458
471
|
|
|
459
472
|
`licenseKey` is validated the same way as `ModelViewer`'s (see [`licenseKey`](#licensekey) below). While the key is being checked, `BindingBuilder` renders a "Verifying license…" placeholder; if it's invalid, it renders an error message instead of the editor.
|
|
460
473
|
|
|
461
|
-
Current behavior
|
|
474
|
+
Current behavior, Object tab:
|
|
462
475
|
|
|
463
476
|
- load the bundled demo model or upload a `.glb`, standalone/data-URI `.gltf`, or `.zip` containing a `.gltf` plus its referenced `.bin` and texture files
|
|
464
477
|
- traverse renderable mesh nodes and generate starter bindings automatically
|
|
@@ -466,9 +479,9 @@ Current behavior — Object tab:
|
|
|
466
479
|
- apply a one-click material preset (wood, metal, chrome, glass, plastic, fabric, ceramic, concrete, etc.) onto the selected object's material
|
|
467
480
|
- undo/redo the current bindings (toolbar buttons or `Cmd/Ctrl+Z` / `Cmd/Ctrl+Shift+Z`); rapid edits coalesce into a single undo step
|
|
468
481
|
- import a previously exported `objectBindings.json`, merged onto the current model by `modelObjectId`
|
|
469
|
-
- export the current bindings as JSON or TypeScript
|
|
482
|
+
- export the current bindings as JSON or TypeScript, bundled into a `.zip` (with a `materials/` folder) when any texture field was filled by uploading a file, otherwise a plain file
|
|
470
483
|
|
|
471
|
-
Current behavior
|
|
484
|
+
Current behavior, Scene tab:
|
|
472
485
|
|
|
473
486
|
- configure the same `SceneConfig` shape `ModelViewer`'s `sceneConfig` prop accepts (lighting, environment, background, ground shadows, wireframe, post-processing, animations, annotations)
|
|
474
487
|
- undo/redo the scene config independently of the Object tab's bindings history
|
|
@@ -509,7 +522,7 @@ export default function App() {
|
|
|
509
522
|
}
|
|
510
523
|
```
|
|
511
524
|
|
|
512
|
-
`SimpleModelViewer` does not take a `licenseKey
|
|
525
|
+
`SimpleModelViewer` does not take a `licenseKey`, licensing is enforced by `ModelViewer` and `BindingBuilder` only.
|
|
513
526
|
|
|
514
527
|
Sizing note:
|
|
515
528
|
|
|
@@ -697,6 +710,7 @@ type Props = {
|
|
|
697
710
|
ktx2TranscoderPath?: string | false;
|
|
698
711
|
meshopt?: boolean;
|
|
699
712
|
showMeasureTools?: boolean;
|
|
713
|
+
showUvCheckerButton?: boolean;
|
|
700
714
|
showExplodeControls?: boolean;
|
|
701
715
|
cinematic?: boolean | CinematicConfig;
|
|
702
716
|
measurementUnit?: string;
|
|
@@ -807,8 +821,8 @@ Optional callback fired when the viewer's built-in UI updates binding data.
|
|
|
807
821
|
This fires for:
|
|
808
822
|
|
|
809
823
|
- visibility toggles (`binding.visible`)
|
|
810
|
-
- color picks (`binding.style.material.baseColor`)
|
|
811
|
-
- texture uploads (`binding.style.material.texture.path`)
|
|
824
|
+
- color picks (`binding.style.material.baseColor`), committed when the color picker closes
|
|
825
|
+
- texture uploads (`binding.style.material.texture.path`), committed immediately (via `onTextureUpload` when provided, otherwise as a blob URL)
|
|
812
826
|
- texture removal (`binding.style.material.texture` cleared)
|
|
813
827
|
|
|
814
828
|
If you want the viewer and your app state to stay in sync, pass `objectBindings` from state and wire this callback back into that state setter.
|
|
@@ -891,7 +905,7 @@ onViewerReady={(viewer) => {
|
|
|
891
905
|
}}
|
|
892
906
|
```
|
|
893
907
|
|
|
894
|
-
Note: requesting a custom `width`/`height` briefly resizes the live canvas to render at that resolution before restoring it, which can cause a momentary flicker on screen
|
|
908
|
+
Note: requesting a custom `width`/`height` briefly resizes the live canvas to render at that resolution before restoring it, which can cause a momentary flicker on screen, fine for an occasional snapshot, not for rapid/looped calls.
|
|
895
909
|
|
|
896
910
|
If you're also using `useViewerCamera`'s `handleViewerReady`, call both from your own `onViewerReady` to get camera helpers and `captureImage` together:
|
|
897
911
|
|
|
@@ -1008,7 +1022,7 @@ function CustomLights() {
|
|
|
1008
1022
|
|
|
1009
1023
|
Optional custom camera configuration passed through to the underlying React Three Fiber `Canvas`.
|
|
1010
1024
|
|
|
1011
|
-
`ModelViewer` only sets a default `fov: 50
|
|
1025
|
+
`ModelViewer` only sets a default `fov: 50`, it does not set a default position, so an unset position falls back to React Three Fiber's own `Canvas` default (`[0, 0, 5]`). Pass an explicit `position` for predictable framing.
|
|
1012
1026
|
|
|
1013
1027
|
Example:
|
|
1014
1028
|
|
|
@@ -1184,7 +1198,7 @@ true;
|
|
|
1184
1198
|
|
|
1185
1199
|
### `showMouseController`
|
|
1186
1200
|
|
|
1187
|
-
Optional boolean that renders an on-screen joystick controller for moving the camera with a mouse or touch
|
|
1201
|
+
Optional boolean that renders an on-screen joystick controller for moving the camera with a mouse or touch, useful on touch devices or kiosk layouts where drag-to-orbit is awkward.
|
|
1188
1202
|
|
|
1189
1203
|
Default:
|
|
1190
1204
|
|
|
@@ -1258,6 +1272,22 @@ Optional scene-wide configuration object (`SceneConfig`) covering model, camera,
|
|
|
1258
1272
|
|
|
1259
1273
|
`sceneConfig.animations` drives autoplay and per-clip playback settings, and `sceneConfig.annotations` seeds the annotation markers rendered on the model.
|
|
1260
1274
|
|
|
1275
|
+
`sceneConfig.model.renderer` accepts `"pbr"`, `"matcap"`, or `"uv-checker"`.
|
|
1276
|
+
UV Checker temporarily replaces every mesh material with an unlit numbered test
|
|
1277
|
+
chart without changing `objectBindings` or uploaded textures. Switching back
|
|
1278
|
+
restores the original material references. Meshes without UV0 coordinates appear
|
|
1279
|
+
magenta and trigger an explanatory notice.
|
|
1280
|
+
|
|
1281
|
+
```tsx
|
|
1282
|
+
<ModelViewer
|
|
1283
|
+
{...props}
|
|
1284
|
+
sceneConfig={{
|
|
1285
|
+
...sceneConfig,
|
|
1286
|
+
model: { ...sceneConfig.model, renderer: "uv-checker" },
|
|
1287
|
+
}}
|
|
1288
|
+
/>
|
|
1289
|
+
```
|
|
1290
|
+
|
|
1261
1291
|
### `disableZoom`
|
|
1262
1292
|
|
|
1263
1293
|
Optional boolean. When `true`, the viewer never zooms the camera to an object on selection (selection still highlights and fires callbacks).
|
|
@@ -1280,7 +1310,7 @@ true;
|
|
|
1280
1310
|
|
|
1281
1311
|
### `onAutoFit`
|
|
1282
1312
|
|
|
1283
|
-
Optional async callback fired once the model has loaded and the scene is ready. When provided, the viewer calls it so consumers can run their own fit-to-scene behavior (e.g. an animated fit); if omitted, the viewer falls back to its internal `fitScene
|
|
1313
|
+
Optional async callback fired once the model has loaded and the scene is ready. When provided, the viewer calls it so consumers can run their own fit-to-scene behavior (e.g. an animated fit); if omitted, the viewer falls back to its internal `fitScene`, unless an explicit [`camera`](#camera) prop was given, in which case that position is treated as the chosen initial view and `fitScene` is skipped.
|
|
1284
1314
|
|
|
1285
1315
|
Current callback shape:
|
|
1286
1316
|
|
|
@@ -1290,7 +1320,7 @@ Current callback shape:
|
|
|
1290
1320
|
|
|
1291
1321
|
### `refitOnResize`
|
|
1292
1322
|
|
|
1293
|
-
Optional boolean controlling whether the camera re-frames the model to fit whenever the canvas is resized
|
|
1323
|
+
Optional boolean controlling whether the camera re-frames the model to fit whenever the canvas is resized, a browser window resize, a device rotation, or a side panel opening/closing (which changes how much width the canvas has). Set to `false` to preserve the user's current orbit/zoom across resizes; the camera aspect stays correct either way, so the model never distorts, it just isn't re-centered. This only affects re-fits _after_ the initial mount-time auto-fit.
|
|
1294
1324
|
|
|
1295
1325
|
Default:
|
|
1296
1326
|
|
|
@@ -1353,9 +1383,9 @@ Optional control over how aggressively the viewer trades visual fidelity for a s
|
|
|
1353
1383
|
performanceProfile?: "auto" | "high" | "low";
|
|
1354
1384
|
```
|
|
1355
1385
|
|
|
1356
|
-
- `"auto"` (default)
|
|
1357
|
-
- `"high"
|
|
1358
|
-
- `"low"
|
|
1386
|
+
- `"auto"` (default), applies a reduced profile on handheld/mobile browsers and other low-power touch devices: the postprocessing pipeline is skipped, soft shadows are disabled, and the device pixel ratio is capped. Desktop-class touch devices may still keep the higher-quality path when they advertise plenty of memory. This keeps mobile GPUs within their memory budget so the context isn't lost, which also keeps WebXR (`enableXR`) usable, since a lost context can't start a session.
|
|
1387
|
+
- `"high"`, always render at full quality (postprocessing, soft shadows, full `maxDpr`), even on mobile. Use when you know the target devices can handle it.
|
|
1388
|
+
- `"low"`, always apply the reduced profile, on any device.
|
|
1359
1389
|
|
|
1360
1390
|
Default:
|
|
1361
1391
|
|
|
@@ -1375,6 +1405,20 @@ meshopt?: boolean;
|
|
|
1375
1405
|
|
|
1376
1406
|
DRACO, Meshopt, and KTX2 decoding are enabled by default via hosted decoder/transcoder bundles, fetched lazily only when the model needs them. Pass a path to self-host the decoder/transcoder files, or `false` to disable that decoder.
|
|
1377
1407
|
|
|
1408
|
+
### `showUvCheckerButton`
|
|
1409
|
+
|
|
1410
|
+
Optional boolean that shows a UV Checker toggle button over the canvas. Turning it on temporarily replaces the model's materials with the numbered diagnostic texture; turning it off restores the renderer configured by `sceneConfig`. Missing UV0 coordinates are shown in magenta.
|
|
1411
|
+
|
|
1412
|
+
```tsx
|
|
1413
|
+
<ModelViewer showUvCheckerButton {...props} />
|
|
1414
|
+
```
|
|
1415
|
+
|
|
1416
|
+
Default:
|
|
1417
|
+
|
|
1418
|
+
```ts
|
|
1419
|
+
false;
|
|
1420
|
+
```
|
|
1421
|
+
|
|
1378
1422
|
### `showMeasureTools`
|
|
1379
1423
|
|
|
1380
1424
|
Optional boolean that shows a click-to-measure toolbar over the canvas: click two points on the model for a distance readout, plus a toggleable bounding-box dimensions overlay.
|
|
@@ -1387,7 +1431,7 @@ false;
|
|
|
1387
1431
|
|
|
1388
1432
|
### `measurementUnit`
|
|
1389
1433
|
|
|
1390
|
-
Optional unit suffix appended to measurement readouts. glTF models are authored in meters by spec, so values are not converted
|
|
1434
|
+
Optional unit suffix appended to measurement readouts. glTF models are authored in meters by spec, so values are not converted, this only changes the displayed label.
|
|
1391
1435
|
|
|
1392
1436
|
Default:
|
|
1393
1437
|
|
|
@@ -1397,7 +1441,7 @@ Default:
|
|
|
1397
1441
|
|
|
1398
1442
|
### `showExplodeControls`
|
|
1399
1443
|
|
|
1400
|
-
Optional boolean that shows an exploded-view slider over the canvas. It slides each bound part outward from the model center to reveal interior/assembly structure, then back to reassemble. Best suited to static product/CAD models
|
|
1444
|
+
Optional boolean that shows an exploded-view slider over the canvas. It slides each bound part outward from the model center to reveal interior/assembly structure, then back to reassemble. Best suited to static product/CAD models, the offset writes node positions each frame, so it conflicts with a playing skeletal animation.
|
|
1401
1445
|
|
|
1402
1446
|
Default:
|
|
1403
1447
|
|
|
@@ -1407,7 +1451,7 @@ false;
|
|
|
1407
1451
|
|
|
1408
1452
|
### `cinematic`
|
|
1409
1453
|
|
|
1410
|
-
Optional cinematic auto-camera. The camera glides along a path on its own, like a film
|
|
1454
|
+
Optional cinematic auto-camera. The camera glides along a path on its own, like a film, ideal for showing off a gallery, apartment, or product with no user interaction. Renders a play/pause button over the canvas; grabbing the camera (or selecting a part) pauses it.
|
|
1411
1455
|
|
|
1412
1456
|
```ts
|
|
1413
1457
|
cinematic?: boolean | CinematicConfig;
|
|
@@ -1429,7 +1473,7 @@ type CinematicWaypoint = {
|
|
|
1429
1473
|
- Two or more `waypoints` author a **walkthrough**: the camera follows a smooth Catmull-Rom spline through them at a constant on-screen speed, looping seamlessly.
|
|
1430
1474
|
- Waypoints are easiest to capture visually in `BindingBuilder`'s **Cinematic** tab, which stores them on `sceneConfig.cinematic`.
|
|
1431
1475
|
|
|
1432
|
-
A path can also come from `sceneConfig.cinematic`. The `cinematic` prop overrides it: a boolean toggles the feature (`true` keeps any authored waypoints, `false` forces it off), and an object overrides field-by-field
|
|
1476
|
+
A path can also come from `sceneConfig.cinematic`. The `cinematic` prop overrides it: a boolean toggles the feature (`true` keeps any authored waypoints, `false` forces it off), and an object overrides field-by-field, so you can keep the authored waypoints while overriding, say, `autoPlay` or `loop`.
|
|
1433
1477
|
|
|
1434
1478
|
```tsx
|
|
1435
1479
|
// Zero-config showcase orbit
|
|
@@ -1465,7 +1509,7 @@ arbitrary uploads and room scenes are framed safely. Set
|
|
|
1465
1509
|
[`arScaleMode`](#arscalemode) to `"real-world"` for product AR, which preserves
|
|
1466
1510
|
the GLB's authored metre scale.
|
|
1467
1511
|
|
|
1468
|
-
**AR placement gestures
|
|
1512
|
+
**AR placement gestures**, inside an AR session the viewer now uses an explicit placement flow:
|
|
1469
1513
|
|
|
1470
1514
|
- before placement, a bottom label says **"Move your device over a flat surface"** until a hit-testable surface is found
|
|
1471
1515
|
- once a surface is found, a reticle appears on it and the label changes to **"Tap to place"**
|
|
@@ -1475,7 +1519,7 @@ the GLB's authored metre scale.
|
|
|
1475
1519
|
|
|
1476
1520
|
VR sessions keep the initial framed placement (there are no real surfaces to hit-test against).
|
|
1477
1521
|
|
|
1478
|
-
> Postprocessing is automatically disabled during an XR session (the effect composer isn't WebXR-aware). Note also that on low-power devices the default [`performanceProfile`](#performanceprofile) of `"auto"` already disables postprocessing and soft shadows
|
|
1522
|
+
> Postprocessing is automatically disabled during an XR session (the effect composer isn't WebXR-aware). Note also that on low-power devices the default [`performanceProfile`](#performanceprofile) of `"auto"` already disables postprocessing and soft shadows, important for keeping the WebGL context alive so AR can start at all.
|
|
1479
1523
|
|
|
1480
1524
|
Default:
|
|
1481
1525
|
|
|
@@ -1586,7 +1630,7 @@ type SimpleModelViewerProps = {
|
|
|
1586
1630
|
};
|
|
1587
1631
|
```
|
|
1588
1632
|
|
|
1589
|
-
`SimpleModelViewer` does not take a `licenseKey
|
|
1633
|
+
`SimpleModelViewer` does not take a `licenseKey`, licensing is enforced by `ModelViewer` and `BindingBuilder` only.
|
|
1590
1634
|
|
|
1591
1635
|
### `modelUrl`
|
|
1592
1636
|
|
|
@@ -1624,7 +1668,7 @@ true;
|
|
|
1624
1668
|
|
|
1625
1669
|
### Scene settings defaults
|
|
1626
1670
|
|
|
1627
|
-
The following optional props seed the initial values of the scene settings (environment) panel. Each maps to one control, and the panel stays interactive so the user can still adjust them at runtime. They are initial values (not controlled props): changing one after mount does not override a value the user has since changed in the panel
|
|
1671
|
+
The following optional props seed the initial values of the scene settings (environment) panel. Each maps to one control, and the panel stays interactive so the user can still adjust them at runtime. They are initial values (not controlled props): changing one after mount does not override a value the user has since changed in the panel, the exception is `backgroundColor`, which stays in sync live.
|
|
1628
1672
|
|
|
1629
1673
|
| Prop | Type | Panel control | Default |
|
|
1630
1674
|
| ---------------------- | ------------- | ----------------------- | ----------- |
|
|
@@ -1683,7 +1727,7 @@ true;
|
|
|
1683
1727
|
|
|
1684
1728
|
### `refitOnResize`
|
|
1685
1729
|
|
|
1686
|
-
Optional boolean controlling whether the camera re-frames the model to fit whenever the canvas is resized
|
|
1730
|
+
Optional boolean controlling whether the camera re-frames the model to fit whenever the canvas is resized, a browser window resize, a device rotation, or a side panel (scene settings / scene objects) opening or closing. Set to `false` to preserve the user's current orbit/zoom across resizes; the camera aspect stays correct either way, so the model never distorts, it just isn't re-centered.
|
|
1687
1731
|
|
|
1688
1732
|
Default:
|
|
1689
1733
|
|
|
@@ -1788,7 +1832,7 @@ At a high level, the current viewer does the following:
|
|
|
1788
1832
|
3. looks up meshes by the keys in `objectBindings` (resolving `modelObjectId` to find the actual model node)
|
|
1789
1833
|
4. clones each referenced material so edits stay isolated per object (keyed on a structural signature of the binding-to-mesh mapping, not the `objectBindings` reference, so materials are not recreated on every binding update)
|
|
1790
1834
|
5. applies runtime color, texture, and style overrides from `objectBindings` in a `useEffect` (not during render)
|
|
1791
|
-
6. manages a reference-counted texture cache so the same texture URL is decoded once and disposed when no longer referenced; each texture is decoded in the correct color space
|
|
1835
|
+
6. manages a reference-counted texture cache so the same texture URL is decoded once and disposed when no longer referenced; each texture is decoded in the correct color space, color maps (base color/albedo, emissive, sheen color, specular color) as sRGB and data maps (normal, roughness, metalness, AO, displacement, etc.) as linear, and the cache is keyed by URL **and** color space, so the same image can be reused safely as both a color and a data map
|
|
1792
1836
|
7. adds hover, selected, and panel-hover emissive highlighting
|
|
1793
1837
|
8. creates an `AnimationMixer` for the loaded scene, ticked every frame via `useFrame`, and exposes playback controls through `onAnimationsReady`
|
|
1794
1838
|
9. renders a side panel for the selected object and its configured actions
|
|
@@ -1800,7 +1844,7 @@ Only objects listed in `objectBindings` are rendered interactively by the curren
|
|
|
1800
1844
|
When `shadows` is enabled (the default), the canvas renders soft shadow maps and the viewer applies:
|
|
1801
1845
|
|
|
1802
1846
|
- a default light rig (`Lights`) with ambient + hemisphere fill and a directional key light that casts shadows, sized to the model
|
|
1803
|
-
- per-mesh `castShadow`/`receiveShadow`, with one exception: the large enclosing "shell" mesh (walls/ceiling of an interior model) is detected by its bounding-box size and excluded from **casting** so a top-down light still reaches the interior
|
|
1847
|
+
- per-mesh `castShadow`/`receiveShadow`, with one exception: the large enclosing "shell" mesh (walls/ceiling of an interior model) is detected by its bounding-box size and excluded from **casting** so a top-down light still reaches the interior, it continues to **receive** shadows, so furniture casts visible contact shadows onto the floor and walls
|
|
1804
1848
|
- a post-processing stack (`EffectComposer`) with SSAO ambient occlusion (normal pass enabled), bloom, vignette, and ACES filmic tone mapping
|
|
1805
1849
|
|
|
1806
1850
|
Pass `shadows={false}` to disable shadow rendering entirely, or pass a custom `lights` rig to replace the default lighting.
|
|
@@ -1841,16 +1885,16 @@ instead of freezing:
|
|
|
1841
1885
|
still works
|
|
1842
1886
|
- a dismissible banner tells the user the model is very large, may render
|
|
1843
1887
|
slowly on their device, and that selection is available through the panel
|
|
1844
|
-
- the loading overlay calls out the extra work
|
|
1888
|
+
- the loading overlay calls out the extra work, uploading that much geometry
|
|
1845
1889
|
to the GPU is a single synchronous operation that can block the page for
|
|
1846
1890
|
tens of seconds in any WebGL viewer
|
|
1847
1891
|
|
|
1848
1892
|
Orbit, zoom, animations, annotations, and the panels keep working. There is no
|
|
1849
|
-
viewer-side way to make models of this size feel fast
|
|
1893
|
+
viewer-side way to make models of this size feel fast, the per-frame cost is
|
|
1850
1894
|
inherent, and on mobile devices the decoded geometry alone can exceed the
|
|
1851
1895
|
tab's memory budget. Decimate such assets at ingestion (to roughly 2–3M
|
|
1852
1896
|
triangles) instead of shipping the raw export; note that very large
|
|
1853
|
-
Draco-compressed files need Blender or native tooling to decimate
|
|
1897
|
+
Draco-compressed files need Blender or native tooling to decimate, the WASM
|
|
1854
1898
|
builds of `gltf-transform` and `gltfpack` cannot decode them within their 4GB
|
|
1855
1899
|
address space.
|
|
1856
1900
|
|
|
@@ -1858,9 +1902,9 @@ Two related picking notes that apply to models of every size:
|
|
|
1858
1902
|
|
|
1859
1903
|
- clicks resolve the front-most surface under the pointer; a mesh with
|
|
1860
1904
|
`selectable: false` does not pass the click through to meshes behind it
|
|
1861
|
-
- `SimpleModelViewer` renders on demand
|
|
1905
|
+
- `SimpleModelViewer` renders on demand, an idle viewer draws no frames, so
|
|
1862
1906
|
it costs no GPU time or battery until something changes
|
|
1863
1907
|
|
|
1864
1908
|
## License
|
|
1865
1909
|
|
|
1866
|
-
Proprietary
|
|
1910
|
+
Proprietary, see [LICENSE](./LICENSE). Installing the package does not itself grant a right to use it in production; a valid `licenseKey` from the [Developer Portal](https://react-immersive.liveroom.dev) is required, and usage is bound to the terms of your license tier.
|
package/dist/index.d.mts
CHANGED
|
@@ -26,10 +26,12 @@ type SceneLightingConfig = {
|
|
|
26
26
|
};
|
|
27
27
|
lights: SceneLight[];
|
|
28
28
|
};
|
|
29
|
+
declare const SCENE_MODEL_RENDERERS: readonly ["pbr", "matcap", "uv-checker"];
|
|
30
|
+
type SceneModelRenderer = (typeof SCENE_MODEL_RENDERERS)[number];
|
|
29
31
|
type SceneModelConfig = {
|
|
30
32
|
rotation: [number, number, number];
|
|
31
33
|
showAdvancedRotation: boolean;
|
|
32
|
-
renderer:
|
|
34
|
+
renderer: SceneModelRenderer;
|
|
33
35
|
shading: "lit" | "unlit" | "normals";
|
|
34
36
|
};
|
|
35
37
|
type SceneCameraConfig = {
|
|
@@ -610,6 +612,7 @@ type ModelViewerProps = {
|
|
|
610
612
|
ktx2TranscoderPath?: string | false;
|
|
611
613
|
meshopt?: boolean;
|
|
612
614
|
showMeasureTools?: boolean;
|
|
615
|
+
showUvCheckerButton?: boolean;
|
|
613
616
|
showExplodeControls?: boolean;
|
|
614
617
|
cinematic?: boolean | CinematicConfig;
|
|
615
618
|
measurementUnit?: string;
|
|
@@ -620,7 +623,7 @@ type ModelViewerProps = {
|
|
|
620
623
|
showAnnotationNavigation?: boolean;
|
|
621
624
|
showAnnotationOnHover?: boolean;
|
|
622
625
|
};
|
|
623
|
-
declare function ModelViewer({ modelUrl, licenseKey, objectBindings, selectedObject, panelHoveredObject, onObjectBindingsChange, onObjectSelect, onObjectHover, onModelLoaded, onLoadError, onAction, onHiddenObjectsChange, onCameraChange, onViewerReady, onTextureUpload, onAnimationsReady, onAnnotationsChange, activeAnnotation: controlledActiveAnnotation, onActiveAnnotationChange, lights, camera, backgroundColor, shadows, showObjectBindingDataPanel, customObjectBindingDataPanel, customSceneObjectsPanel, showSceneObjectsPanel, showDownloadButton, downloadFilename, showResetButton, showLoadingOverlay, showMouseController, mouseControllerPosition, mouseControllerOpacity, moveSensitivity, zoomSensitivity, sceneConfig, disableZoom, zoomOnSelected, highlightOnHover, onAutoFit, refitOnResize, renderMode, maxDpr, performanceProfile, dracoDecoderPath, ktx2TranscoderPath, meshopt, showMeasureTools, showExplodeControls, cinematic, measurementUnit, enableXR, usdzUrl, arScaleMode, mobileHandoffUrl, showAnnotationNavigation, showAnnotationOnHover, }: ModelViewerProps): react_jsx_runtime.JSX.Element;
|
|
626
|
+
declare function ModelViewer({ modelUrl, licenseKey, objectBindings, selectedObject, panelHoveredObject, onObjectBindingsChange, onObjectSelect, onObjectHover, onModelLoaded, onLoadError, onAction, onHiddenObjectsChange, onCameraChange, onViewerReady, onTextureUpload, onAnimationsReady, onAnnotationsChange, activeAnnotation: controlledActiveAnnotation, onActiveAnnotationChange, lights, camera, backgroundColor, shadows, showObjectBindingDataPanel, customObjectBindingDataPanel, customSceneObjectsPanel, showSceneObjectsPanel, showDownloadButton, downloadFilename, showResetButton, showLoadingOverlay, showMouseController, mouseControllerPosition, mouseControllerOpacity, moveSensitivity, zoomSensitivity, sceneConfig, disableZoom, zoomOnSelected, highlightOnHover, onAutoFit, refitOnResize, renderMode, maxDpr, performanceProfile, dracoDecoderPath, ktx2TranscoderPath, meshopt, showMeasureTools, showUvCheckerButton, showExplodeControls, cinematic, measurementUnit, enableXR, usdzUrl, arScaleMode, mobileHandoffUrl, showAnnotationNavigation, showAnnotationOnHover, }: ModelViewerProps): react_jsx_runtime.JSX.Element;
|
|
624
627
|
|
|
625
628
|
declare function BindingBuilder({ licenseKey }: {
|
|
626
629
|
licenseKey: string;
|
|
@@ -661,17 +664,55 @@ declare function useObjectBinding(objectBindings: Record<string, ObjectBinding>,
|
|
|
661
664
|
|
|
662
665
|
declare function useObjectBindingIds(objectBindings: Record<string, ObjectBinding>): string[];
|
|
663
666
|
|
|
667
|
+
type DeepPartial<T> = T extends (infer _U)[] ? T : T extends object ? {
|
|
668
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
669
|
+
} : T;
|
|
670
|
+
type ObjectBindingPatch = DeepPartial<ObjectBinding>;
|
|
671
|
+
type BindingEdit = {
|
|
672
|
+
ids: string | string[];
|
|
673
|
+
patch: ObjectBindingPatch;
|
|
674
|
+
};
|
|
675
|
+
/**
|
|
676
|
+
* Applies field-level patches to object bindings and returns the updated
|
|
677
|
+
* record. Pure — nothing is mutated, and the original reference comes back
|
|
678
|
+
* untouched when no id matched, so React can skip the re-render.
|
|
679
|
+
*
|
|
680
|
+
* Ids resolve the same way everywhere else in the library: binding key first,
|
|
681
|
+
* then `binding.id`, then `binding.modelObjectId`.
|
|
682
|
+
*/
|
|
683
|
+
declare function patchBindings(bindings: Record<string, ObjectBinding>, objectId: string | string[], patch: ObjectBindingPatch): Record<string, ObjectBinding>;
|
|
684
|
+
declare function patchBindings(bindings: Record<string, ObjectBinding>, edits: BindingEdit[]): Record<string, ObjectBinding>;
|
|
685
|
+
/** Shorthand for the common `{ style: { material: … } }` nesting. */
|
|
686
|
+
declare function material(value: ObjectBindingMaterial): ObjectBindingPatch;
|
|
687
|
+
|
|
664
688
|
type HiddenObjectsState = Record<string, boolean>;
|
|
665
|
-
type
|
|
689
|
+
type ObjectBindingsController = {
|
|
690
|
+
objectBindings: Record<string, ObjectBinding>;
|
|
691
|
+
setObjectBindings: React.Dispatch<React.SetStateAction<Record<string, ObjectBinding>>>;
|
|
692
|
+
patch: {
|
|
693
|
+
(objectId: string | string[], patch: ObjectBindingPatch): void;
|
|
694
|
+
(edits: BindingEdit[]): void;
|
|
695
|
+
};
|
|
696
|
+
setMaterial: (objectId: string | string[], material: ObjectBindingMaterial) => void;
|
|
697
|
+
setBaseColor: (objectId: string | string[], color: string) => void;
|
|
698
|
+
resetMaterial: (objectId: string | string[]) => void;
|
|
699
|
+
getMaterial: (objectId: string) => ObjectBindingMaterial | null;
|
|
666
700
|
hiddenObjects: HiddenObjectsState;
|
|
667
701
|
hiddenObjectIds: string[];
|
|
668
|
-
hideObject: (objectId: string) => void;
|
|
669
|
-
showObject: (objectId: string) => void;
|
|
670
|
-
toggleObjectVisibility: (objectId: string) => void;
|
|
702
|
+
hideObject: (objectId: string | string[]) => void;
|
|
703
|
+
showObject: (objectId: string | string[]) => void;
|
|
704
|
+
toggleObjectVisibility: (objectId: string | string[]) => void;
|
|
671
705
|
isObjectHidden: (objectId: string) => boolean;
|
|
672
706
|
clearHiddenObjects: () => void;
|
|
673
707
|
};
|
|
674
|
-
|
|
708
|
+
/**
|
|
709
|
+
* Owns object-binding state and exposes field-level, material, and visibility
|
|
710
|
+
* operations over the same functional state updater.
|
|
711
|
+
*
|
|
712
|
+
* Consecutive calls in the same tick compose instead of overwriting each other,
|
|
713
|
+
* including calls across material and visibility concerns.
|
|
714
|
+
*/
|
|
715
|
+
declare function useObjectBindings(initialBindings: Record<string, ObjectBinding> | (() => Record<string, ObjectBinding>)): ObjectBindingsController;
|
|
675
716
|
|
|
676
717
|
type ViewerHoverProps = {
|
|
677
718
|
hoveredObjectBinding: ObjectBinding | null;
|
|
@@ -725,4 +766,4 @@ type ShareableViewerStateProps = {
|
|
|
725
766
|
};
|
|
726
767
|
declare function useShareableViewerState({ cameraState, setCameraState, objectBindings, onObjectBindingsChange, selectedObjectBinding, setSelectedObjectBinding, paramKey, debounceMs, autoSync, }: UseShareableViewerStateOptions): ShareableViewerStateProps;
|
|
727
768
|
|
|
728
|
-
export { type AnimationClipInfo, type AnimationControls, type AnimationLoopMode, type AnimationPlaybackState, BindingBuilder, type CaptureImageOptions, type CinematicConfig, type CinematicWaypoint, type CustomObjectBindingDataPanelProps, type CustomSceneObjectsPanelProps, type HiddenObjectsState, type HomeCameraState, MATERIAL_BLENDING_MODES, MATERIAL_SIDES, ModelViewer, type ModelViewerProps, type ObjectActionEvent, type ObjectBinding, type ObjectBindingAction, type ObjectBindingMaterial, type ObjectBindingMaterialBlendingMode, type ObjectBindingMaterialSide, type ObjectBindingTextureSlot, type
|
|
769
|
+
export { type AnimationClipInfo, type AnimationControls, type AnimationLoopMode, type AnimationPlaybackState, BindingBuilder, type BindingEdit, type CaptureImageOptions, type CinematicConfig, type CinematicWaypoint, type CustomObjectBindingDataPanelProps, type CustomSceneObjectsPanelProps, type HiddenObjectsState, type HomeCameraState, MATERIAL_BLENDING_MODES, MATERIAL_SIDES, ModelViewer, type ModelViewerProps, type ObjectActionEvent, type ObjectBinding, type ObjectBindingAction, type ObjectBindingMaterial, type ObjectBindingMaterialBlendingMode, type ObjectBindingMaterialSide, type ObjectBindingPatch, type ObjectBindingTextureSlot, type ObjectBindingsController, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, type SceneModelRenderer, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, type XRScaleMode, material, patchBindings, useObjectBinding, useObjectBindingIds, useObjectBindings, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|