@liveroom-tech/react-immersive 1.1.6 → 1.1.8
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 +22 -1
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +11 -6
- package/dist/index.mjs +11 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -701,6 +701,8 @@ type Props = {
|
|
|
701
701
|
measurementUnit?: string;
|
|
702
702
|
enableXR?: boolean;
|
|
703
703
|
usdzUrl?: string;
|
|
704
|
+
arScaleMode?: "normalized" | "real-world";
|
|
705
|
+
mobileHandoffUrl?: string;
|
|
704
706
|
showAnnotationNavigation?: boolean;
|
|
705
707
|
};
|
|
706
708
|
```
|
|
@@ -1448,7 +1450,11 @@ Default: disabled.
|
|
|
1448
1450
|
|
|
1449
1451
|
Optional boolean that enables XR entry points. On WebXR-capable browsers, the viewer shows a **"View in your space"** (AR) and/or **"Enter VR"** button once `navigator.xr.isSessionSupported(...)` resolves `true` for that mode. On iPhone/iPad, WebXR AR is not available, but if you also pass [`usdzUrl`](#usdzUrl), the viewer shows a **"View in AR"** button that launches Apple Quick Look instead.
|
|
1450
1452
|
|
|
1451
|
-
On entering a session the model is
|
|
1453
|
+
On entering a session the model is rested on the floor a short distance in front
|
|
1454
|
+
of the viewer. By default it is normalized to ~1 m on its longest axis so
|
|
1455
|
+
arbitrary uploads and room scenes are framed safely. Set
|
|
1456
|
+
[`arScaleMode`](#arscalemode) to `"real-world"` for product AR, which preserves
|
|
1457
|
+
the GLB's authored metre scale.
|
|
1452
1458
|
|
|
1453
1459
|
**AR placement gestures** — inside an AR session the viewer now uses an explicit placement flow:
|
|
1454
1460
|
|
|
@@ -1485,6 +1491,21 @@ Notes:
|
|
|
1485
1491
|
- Android / WebXR-capable devices ignore this and continue using the normal WebXR AR flow
|
|
1486
1492
|
- if `usdzUrl` is omitted, Apple handheld devices simply won't get an AR button
|
|
1487
1493
|
|
|
1494
|
+
### `arScaleMode`
|
|
1495
|
+
|
|
1496
|
+
Controls the initial model size inside WebXR AR and VR sessions.
|
|
1497
|
+
|
|
1498
|
+
```ts
|
|
1499
|
+
arScaleMode?: "normalized" | "real-world";
|
|
1500
|
+
```
|
|
1501
|
+
|
|
1502
|
+
- `"normalized"` (default) fits the longest model dimension to approximately
|
|
1503
|
+
1 metre. Use this for arbitrary uploads and room-scale scenes.
|
|
1504
|
+
- `"real-world"` preserves the GLB's authored scale. glTF units are metres, so
|
|
1505
|
+
use this for product models exported at their real dimensions.
|
|
1506
|
+
|
|
1507
|
+
Users can still pinch to resize after placement in either mode.
|
|
1508
|
+
|
|
1488
1509
|
### `showAnnotationNavigation`
|
|
1489
1510
|
|
|
1490
1511
|
Optional boolean that shows the "Guided Tour" control cluster when the model has at least one annotation: a single "Guided Tour" button that, once started, becomes Previous/Stop/Next controls for stepping through annotations in order.
|
package/dist/index.d.mts
CHANGED
|
@@ -344,6 +344,8 @@ declare function Viewer({ children, camera, backgroundColor, shadows, sceneConfi
|
|
|
344
344
|
|
|
345
345
|
type PerformanceProfile = "auto" | "high" | "low";
|
|
346
346
|
|
|
347
|
+
type XRScaleMode = "normalized" | "real-world";
|
|
348
|
+
|
|
347
349
|
type CinematicWaypoint = {
|
|
348
350
|
position: [number, number, number];
|
|
349
351
|
target: [number, number, number];
|
|
@@ -604,10 +606,11 @@ type ModelViewerProps = {
|
|
|
604
606
|
measurementUnit?: string;
|
|
605
607
|
enableXR?: boolean;
|
|
606
608
|
usdzUrl?: string;
|
|
609
|
+
arScaleMode?: XRScaleMode;
|
|
607
610
|
mobileHandoffUrl?: string;
|
|
608
611
|
showAnnotationNavigation?: boolean;
|
|
609
612
|
};
|
|
610
|
-
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, mobileHandoffUrl, showAnnotationNavigation, }: ModelViewerProps): react_jsx_runtime.JSX.Element;
|
|
613
|
+
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, }: ModelViewerProps): react_jsx_runtime.JSX.Element;
|
|
611
614
|
|
|
612
615
|
declare function BindingBuilder({ licenseKey }: {
|
|
613
616
|
licenseKey: string;
|
|
@@ -712,4 +715,4 @@ type ShareableViewerStateProps = {
|
|
|
712
715
|
};
|
|
713
716
|
declare function useShareableViewerState({ cameraState, setCameraState, objectBindings, onObjectBindingsChange, selectedObjectBinding, setSelectedObjectBinding, paramKey, debounceMs, autoSync, }: UseShareableViewerStateOptions): ShareableViewerStateProps;
|
|
714
717
|
|
|
715
|
-
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 ObjectVisibilityProps, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, useObjectBinding, useObjectBindingIds, useObjectVisibility, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|
|
718
|
+
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 ObjectVisibilityProps, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, type XRScaleMode, useObjectBinding, useObjectBindingIds, useObjectVisibility, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|
package/dist/index.d.ts
CHANGED
|
@@ -344,6 +344,8 @@ declare function Viewer({ children, camera, backgroundColor, shadows, sceneConfi
|
|
|
344
344
|
|
|
345
345
|
type PerformanceProfile = "auto" | "high" | "low";
|
|
346
346
|
|
|
347
|
+
type XRScaleMode = "normalized" | "real-world";
|
|
348
|
+
|
|
347
349
|
type CinematicWaypoint = {
|
|
348
350
|
position: [number, number, number];
|
|
349
351
|
target: [number, number, number];
|
|
@@ -604,10 +606,11 @@ type ModelViewerProps = {
|
|
|
604
606
|
measurementUnit?: string;
|
|
605
607
|
enableXR?: boolean;
|
|
606
608
|
usdzUrl?: string;
|
|
609
|
+
arScaleMode?: XRScaleMode;
|
|
607
610
|
mobileHandoffUrl?: string;
|
|
608
611
|
showAnnotationNavigation?: boolean;
|
|
609
612
|
};
|
|
610
|
-
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, mobileHandoffUrl, showAnnotationNavigation, }: ModelViewerProps): react_jsx_runtime.JSX.Element;
|
|
613
|
+
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, }: ModelViewerProps): react_jsx_runtime.JSX.Element;
|
|
611
614
|
|
|
612
615
|
declare function BindingBuilder({ licenseKey }: {
|
|
613
616
|
licenseKey: string;
|
|
@@ -712,4 +715,4 @@ type ShareableViewerStateProps = {
|
|
|
712
715
|
};
|
|
713
716
|
declare function useShareableViewerState({ cameraState, setCameraState, objectBindings, onObjectBindingsChange, selectedObjectBinding, setSelectedObjectBinding, paramKey, debounceMs, autoSync, }: UseShareableViewerStateOptions): ShareableViewerStateProps;
|
|
714
717
|
|
|
715
|
-
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 ObjectVisibilityProps, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, useObjectBinding, useObjectBindingIds, useObjectVisibility, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|
|
718
|
+
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 ObjectVisibilityProps, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, type XRScaleMode, useObjectBinding, useObjectBindingIds, useObjectVisibility, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|
package/dist/index.js
CHANGED
|
@@ -3631,12 +3631,15 @@ var TARGET_SIZE = 1;
|
|
|
3631
3631
|
var FORWARD_DISTANCE = 1;
|
|
3632
3632
|
var MIN_USER_SCALE = 0.1;
|
|
3633
3633
|
var MAX_USER_SCALE = 10;
|
|
3634
|
-
function computeNormalization(box) {
|
|
3634
|
+
function computeNormalization(box, scaleMode) {
|
|
3635
3635
|
const [sx, sy, sz] = box.size;
|
|
3636
3636
|
const cx = (box.min[0] + box.max[0]) / 2;
|
|
3637
3637
|
const cz = (box.min[2] + box.max[2]) / 2;
|
|
3638
3638
|
const maxDim = Math.max(sx, sy, sz) || 1;
|
|
3639
|
-
return {
|
|
3639
|
+
return {
|
|
3640
|
+
scale: scaleMode === "real-world" ? 1 : TARGET_SIZE / maxDim,
|
|
3641
|
+
offset: [-cx, -box.min[1], -cz]
|
|
3642
|
+
};
|
|
3640
3643
|
}
|
|
3641
3644
|
function touchDistance(touches) {
|
|
3642
3645
|
const dx = touches[0].clientX - touches[1].clientX;
|
|
@@ -3649,15 +3652,15 @@ function touchAngle(touches) {
|
|
|
3649
3652
|
return Math.atan2(dy, dx);
|
|
3650
3653
|
}
|
|
3651
3654
|
var XRModelPresenter = (0, import_react14.forwardRef)(
|
|
3652
|
-
function XRModelPresenter2({ box, children, onARStateChange }, ref) {
|
|
3655
|
+
function XRModelPresenter2({ box, scaleMode, children, onARStateChange }, ref) {
|
|
3653
3656
|
const placementRef = (0, import_react14.useRef)(null);
|
|
3654
3657
|
const scaleRef = (0, import_react14.useRef)(null);
|
|
3655
3658
|
const reticleRef = (0, import_react14.useRef)(null);
|
|
3656
3659
|
const inSession = (0, import_xr3.useXR)((state) => state.session != null);
|
|
3657
3660
|
const isAR = (0, import_xr3.useXR)((state) => state.mode === "immersive-ar");
|
|
3658
3661
|
const normalization = (0, import_react14.useMemo)(
|
|
3659
|
-
() => box ? computeNormalization(box) : null,
|
|
3660
|
-
[box]
|
|
3662
|
+
() => box ? computeNormalization(box, scaleMode) : null,
|
|
3663
|
+
[box, scaleMode]
|
|
3661
3664
|
);
|
|
3662
3665
|
const placedPosition = (0, import_react14.useRef)(new import_three16.Vector3(0, 0, -FORWARD_DISTANCE));
|
|
3663
3666
|
const userScale = (0, import_react14.useRef)(1);
|
|
@@ -4214,7 +4217,7 @@ var useLicense = (licenseKey) => {
|
|
|
4214
4217
|
var import_react17 = require("react");
|
|
4215
4218
|
|
|
4216
4219
|
// src/styles/MouseController.css
|
|
4217
|
-
styleInject(".mc__wrapper {\n position:
|
|
4220
|
+
styleInject(".mc__wrapper {\n position: absolute;\n bottom: -10px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n flex-direction: column;\n align-items: center;\n z-index: 100;\n}\n.mc__dpad {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n margin-bottom: 20px;\n}\n.mc__middle-row {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n.mc__joystick {\n width: 60px;\n height: 60px;\n flex-shrink: 0;\n background:\n radial-gradient(\n circle at 40% 35%,\n rgba(255, 255, 255, 0.07),\n rgba(0, 0, 0, 0.55));\n border-radius: 50%;\n border: 1.5px solid rgba(255, 255, 255, 0.15);\n position: relative;\n cursor: grab;\n touch-action: none;\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n margin: 4px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5), 0 0 0 4px rgba(255, 255, 255, 0.03);\n}\n.mc__joystick:hover {\n border-color: rgba(255, 255, 255, 0.28);\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.55), 0 0 0 4px rgba(66, 133, 244, 0.08);\n}\n.mc__joystick:active {\n cursor: grabbing;\n border-color: rgba(66, 133, 244, 0.6);\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5), 0 0 4px rgba(66, 133, 244, 0.15);\n}\n.mc__knob {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 34px;\n height: 34px;\n margin-left: -17px;\n margin-top: -17px;\n background:\n linear-gradient(\n 145deg,\n #5a9bf5,\n #1a66d9);\n border-radius: 50%;\n cursor: grab;\n box-shadow: 0 3px 10px rgba(26, 102, 217, 0.5), 0 1px 0 rgba(255, 255, 255, 0.25) inset;\n transition: transform 0.04s linear, box-shadow 0.1s ease;\n border: 1.5px solid rgba(255, 255, 255, 0.45);\n}\n.mc__joystick:active .mc__knob {\n box-shadow: 0 2px 16px rgba(66, 133, 244, 0.7), 0 1px 0 rgba(255, 255, 255, 0.25) inset;\n animation: pulse 0.6s ease infinite;\n}\n.mc__arrow {\n padding: 0;\n margin: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n box-shadow: none;\n outline: none;\n -webkit-appearance: none;\n appearance: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n touch-action: manipulation;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n transition: transform 0.1s ease, filter 0.15s ease;\n overflow: visible;\n}\n.mc__arrow svg {\n display: block !important;\n pointer-events: none !important;\n user-select: none !important;\n -webkit-user-select: none !important;\n overflow: visible !important;\n}\n.mc__arrow--up {\n margin-bottom: 2px;\n}\n.mc__arrow--up:hover {\n transform: scale(1.15) translateY(-2px);\n filter: drop-shadow(0 4px 12px rgba(66, 133, 244, 0.8));\n}\n.mc__arrow--up:active {\n transform: scale(0.92) translateY(2px);\n}\n.mc__arrow--down {\n margin-top: 2px;\n}\n.mc__arrow--down:hover {\n transform: scale(1.15) translateY(2px);\n filter: drop-shadow(0 -4px 12px rgba(66, 133, 244, 0.8));\n}\n.mc__arrow--down:active {\n transform: scale(0.92) translateY(-2px);\n}\n.mc__arrow--left {\n margin-right: 2px;\n}\n.mc__arrow--left:hover {\n transform: scale(1.15) translateX(-2px);\n filter: drop-shadow(4px 0 12px rgba(66, 133, 244, 0.8));\n}\n.mc__arrow--left:active {\n transform: scale(0.92) translateX(2px);\n}\n.mc__arrow--right {\n margin-left: 2px;\n}\n.mc__arrow--right:hover {\n transform: scale(1.15) translateX(2px);\n filter: drop-shadow(-4px 0 12px rgba(66, 133, 244, 0.8));\n}\n.mc__arrow--right:active {\n transform: scale(0.92) translateX(-2px);\n}\n@keyframes pulse {\n 0%, 100% {\n box-shadow: 0 2px 16px rgba(66, 133, 244, 0.6), 0 1px 0 rgba(255, 255, 255, 0.25) inset;\n opacity: 0.85;\n }\n 50% {\n box-shadow: 0 4px 24px rgba(66, 133, 244, 0.95), 0 1px 0 rgba(255, 255, 255, 0.25) inset;\n opacity: 1;\n }\n}\n@media (max-width: 768px) {\n .mc__wrapper {\n bottom: -5px;\n }\n .mc__joystick {\n width: 68px;\n height: 68px;\n }\n .mc__knob {\n width: 30px;\n height: 30px;\n margin-left: -15px;\n margin-top: -15px;\n }\n .mc__arrow--up:hover {\n transform: scale(1.1) translateY(-1px);\n }\n .mc__arrow--down:hover {\n transform: scale(1.1) translateY(1px);\n }\n .mc__arrow--left:hover {\n transform: scale(1.1) translateX(-1px);\n }\n .mc__arrow--right:hover {\n transform: scale(1.1) translateX(1px);\n }\n}\n@media (max-width: 480px) {\n .mc__joystick {\n width: 56px;\n height: 56px;\n }\n .mc__knob {\n width: 26px;\n height: 26px;\n margin-left: -13px;\n margin-top: -13px;\n }\n .mc__arrow--up {\n margin-bottom: 1px;\n }\n .mc__arrow--down {\n margin-top: 1px;\n }\n .mc__arrow--left {\n margin-right: 1px;\n }\n .mc__arrow--right {\n margin-left: 1px;\n }\n}\n@media (hover: none) {\n .mc__arrow:hover {\n transform: none !important;\n filter: none !important;\n }\n .mc__arrow:active {\n transform: scale(0.92) !important;\n }\n}\n");
|
|
4218
4221
|
|
|
4219
4222
|
// src/components/MouseController.tsx
|
|
4220
4223
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
@@ -5221,6 +5224,7 @@ function ModelViewer({
|
|
|
5221
5224
|
measurementUnit = "m",
|
|
5222
5225
|
enableXR = false,
|
|
5223
5226
|
usdzUrl,
|
|
5227
|
+
arScaleMode = "normalized",
|
|
5224
5228
|
mobileHandoffUrl,
|
|
5225
5229
|
showAnnotationNavigation = true
|
|
5226
5230
|
}) {
|
|
@@ -6784,6 +6788,7 @@ function ModelViewer({
|
|
|
6784
6788
|
{
|
|
6785
6789
|
ref: xrPresenterRef,
|
|
6786
6790
|
box: measureBox,
|
|
6791
|
+
scaleMode: arScaleMode,
|
|
6787
6792
|
onARStateChange: handleARStateChange,
|
|
6788
6793
|
children: modelContent
|
|
6789
6794
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -3672,12 +3672,15 @@ var TARGET_SIZE = 1;
|
|
|
3672
3672
|
var FORWARD_DISTANCE = 1;
|
|
3673
3673
|
var MIN_USER_SCALE = 0.1;
|
|
3674
3674
|
var MAX_USER_SCALE = 10;
|
|
3675
|
-
function computeNormalization(box) {
|
|
3675
|
+
function computeNormalization(box, scaleMode) {
|
|
3676
3676
|
const [sx, sy, sz] = box.size;
|
|
3677
3677
|
const cx = (box.min[0] + box.max[0]) / 2;
|
|
3678
3678
|
const cz = (box.min[2] + box.max[2]) / 2;
|
|
3679
3679
|
const maxDim = Math.max(sx, sy, sz) || 1;
|
|
3680
|
-
return {
|
|
3680
|
+
return {
|
|
3681
|
+
scale: scaleMode === "real-world" ? 1 : TARGET_SIZE / maxDim,
|
|
3682
|
+
offset: [-cx, -box.min[1], -cz]
|
|
3683
|
+
};
|
|
3681
3684
|
}
|
|
3682
3685
|
function touchDistance(touches) {
|
|
3683
3686
|
const dx = touches[0].clientX - touches[1].clientX;
|
|
@@ -3690,15 +3693,15 @@ function touchAngle(touches) {
|
|
|
3690
3693
|
return Math.atan2(dy, dx);
|
|
3691
3694
|
}
|
|
3692
3695
|
var XRModelPresenter = forwardRef2(
|
|
3693
|
-
function XRModelPresenter2({ box, children, onARStateChange }, ref) {
|
|
3696
|
+
function XRModelPresenter2({ box, scaleMode, children, onARStateChange }, ref) {
|
|
3694
3697
|
const placementRef = useRef7(null);
|
|
3695
3698
|
const scaleRef = useRef7(null);
|
|
3696
3699
|
const reticleRef = useRef7(null);
|
|
3697
3700
|
const inSession = useXR2((state) => state.session != null);
|
|
3698
3701
|
const isAR = useXR2((state) => state.mode === "immersive-ar");
|
|
3699
3702
|
const normalization = useMemo10(
|
|
3700
|
-
() => box ? computeNormalization(box) : null,
|
|
3701
|
-
[box]
|
|
3703
|
+
() => box ? computeNormalization(box, scaleMode) : null,
|
|
3704
|
+
[box, scaleMode]
|
|
3702
3705
|
);
|
|
3703
3706
|
const placedPosition = useRef7(new Vector35(0, 0, -FORWARD_DISTANCE));
|
|
3704
3707
|
const userScale = useRef7(1);
|
|
@@ -4260,7 +4263,7 @@ var useLicense = (licenseKey) => {
|
|
|
4260
4263
|
import { useRef as useRef9, useState as useState6, useCallback as useCallback3, useEffect as useEffect12 } from "react";
|
|
4261
4264
|
|
|
4262
4265
|
// src/styles/MouseController.css
|
|
4263
|
-
styleInject(".mc__wrapper {\n position:
|
|
4266
|
+
styleInject(".mc__wrapper {\n position: absolute;\n bottom: -10px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n flex-direction: column;\n align-items: center;\n z-index: 100;\n}\n.mc__dpad {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n margin-bottom: 20px;\n}\n.mc__middle-row {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n.mc__joystick {\n width: 60px;\n height: 60px;\n flex-shrink: 0;\n background:\n radial-gradient(\n circle at 40% 35%,\n rgba(255, 255, 255, 0.07),\n rgba(0, 0, 0, 0.55));\n border-radius: 50%;\n border: 1.5px solid rgba(255, 255, 255, 0.15);\n position: relative;\n cursor: grab;\n touch-action: none;\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n margin: 4px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5), 0 0 0 4px rgba(255, 255, 255, 0.03);\n}\n.mc__joystick:hover {\n border-color: rgba(255, 255, 255, 0.28);\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.55), 0 0 0 4px rgba(66, 133, 244, 0.08);\n}\n.mc__joystick:active {\n cursor: grabbing;\n border-color: rgba(66, 133, 244, 0.6);\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5), 0 0 4px rgba(66, 133, 244, 0.15);\n}\n.mc__knob {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 34px;\n height: 34px;\n margin-left: -17px;\n margin-top: -17px;\n background:\n linear-gradient(\n 145deg,\n #5a9bf5,\n #1a66d9);\n border-radius: 50%;\n cursor: grab;\n box-shadow: 0 3px 10px rgba(26, 102, 217, 0.5), 0 1px 0 rgba(255, 255, 255, 0.25) inset;\n transition: transform 0.04s linear, box-shadow 0.1s ease;\n border: 1.5px solid rgba(255, 255, 255, 0.45);\n}\n.mc__joystick:active .mc__knob {\n box-shadow: 0 2px 16px rgba(66, 133, 244, 0.7), 0 1px 0 rgba(255, 255, 255, 0.25) inset;\n animation: pulse 0.6s ease infinite;\n}\n.mc__arrow {\n padding: 0;\n margin: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n box-shadow: none;\n outline: none;\n -webkit-appearance: none;\n appearance: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n touch-action: manipulation;\n user-select: none;\n -webkit-tap-highlight-color: transparent;\n transition: transform 0.1s ease, filter 0.15s ease;\n overflow: visible;\n}\n.mc__arrow svg {\n display: block !important;\n pointer-events: none !important;\n user-select: none !important;\n -webkit-user-select: none !important;\n overflow: visible !important;\n}\n.mc__arrow--up {\n margin-bottom: 2px;\n}\n.mc__arrow--up:hover {\n transform: scale(1.15) translateY(-2px);\n filter: drop-shadow(0 4px 12px rgba(66, 133, 244, 0.8));\n}\n.mc__arrow--up:active {\n transform: scale(0.92) translateY(2px);\n}\n.mc__arrow--down {\n margin-top: 2px;\n}\n.mc__arrow--down:hover {\n transform: scale(1.15) translateY(2px);\n filter: drop-shadow(0 -4px 12px rgba(66, 133, 244, 0.8));\n}\n.mc__arrow--down:active {\n transform: scale(0.92) translateY(-2px);\n}\n.mc__arrow--left {\n margin-right: 2px;\n}\n.mc__arrow--left:hover {\n transform: scale(1.15) translateX(-2px);\n filter: drop-shadow(4px 0 12px rgba(66, 133, 244, 0.8));\n}\n.mc__arrow--left:active {\n transform: scale(0.92) translateX(2px);\n}\n.mc__arrow--right {\n margin-left: 2px;\n}\n.mc__arrow--right:hover {\n transform: scale(1.15) translateX(2px);\n filter: drop-shadow(-4px 0 12px rgba(66, 133, 244, 0.8));\n}\n.mc__arrow--right:active {\n transform: scale(0.92) translateX(-2px);\n}\n@keyframes pulse {\n 0%, 100% {\n box-shadow: 0 2px 16px rgba(66, 133, 244, 0.6), 0 1px 0 rgba(255, 255, 255, 0.25) inset;\n opacity: 0.85;\n }\n 50% {\n box-shadow: 0 4px 24px rgba(66, 133, 244, 0.95), 0 1px 0 rgba(255, 255, 255, 0.25) inset;\n opacity: 1;\n }\n}\n@media (max-width: 768px) {\n .mc__wrapper {\n bottom: -5px;\n }\n .mc__joystick {\n width: 68px;\n height: 68px;\n }\n .mc__knob {\n width: 30px;\n height: 30px;\n margin-left: -15px;\n margin-top: -15px;\n }\n .mc__arrow--up:hover {\n transform: scale(1.1) translateY(-1px);\n }\n .mc__arrow--down:hover {\n transform: scale(1.1) translateY(1px);\n }\n .mc__arrow--left:hover {\n transform: scale(1.1) translateX(-1px);\n }\n .mc__arrow--right:hover {\n transform: scale(1.1) translateX(1px);\n }\n}\n@media (max-width: 480px) {\n .mc__joystick {\n width: 56px;\n height: 56px;\n }\n .mc__knob {\n width: 26px;\n height: 26px;\n margin-left: -13px;\n margin-top: -13px;\n }\n .mc__arrow--up {\n margin-bottom: 1px;\n }\n .mc__arrow--down {\n margin-top: 1px;\n }\n .mc__arrow--left {\n margin-right: 1px;\n }\n .mc__arrow--right {\n margin-left: 1px;\n }\n}\n@media (hover: none) {\n .mc__arrow:hover {\n transform: none !important;\n filter: none !important;\n }\n .mc__arrow:active {\n transform: scale(0.92) !important;\n }\n}\n");
|
|
4264
4267
|
|
|
4265
4268
|
// src/components/MouseController.tsx
|
|
4266
4269
|
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
@@ -5287,6 +5290,7 @@ function ModelViewer({
|
|
|
5287
5290
|
measurementUnit = "m",
|
|
5288
5291
|
enableXR = false,
|
|
5289
5292
|
usdzUrl,
|
|
5293
|
+
arScaleMode = "normalized",
|
|
5290
5294
|
mobileHandoffUrl,
|
|
5291
5295
|
showAnnotationNavigation = true
|
|
5292
5296
|
}) {
|
|
@@ -6850,6 +6854,7 @@ function ModelViewer({
|
|
|
6850
6854
|
{
|
|
6851
6855
|
ref: xrPresenterRef,
|
|
6852
6856
|
box: measureBox,
|
|
6857
|
+
scaleMode: arScaleMode,
|
|
6853
6858
|
onARStateChange: handleARStateChange,
|
|
6854
6859
|
children: modelContent
|
|
6855
6860
|
}
|