@neurodyn/react-room-viewer 0.0.6 → 0.0.7
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/dist/index.d.ts +10 -0
- package/dist/index.js +249 -20
- package/dist/static/image/arrows-rug.png +0 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -53,6 +53,11 @@ declare const resources: {
|
|
|
53
53
|
readonly scanQrCode: "Scan this QR code with your phone's camera to view the object in Augmented Reality";
|
|
54
54
|
readonly deviceRequirementsDisclaimer: "*Requires AR-supported device and browser. We recommend iOS 12 or later with Safari, or Android 7.0 or later with Chrome.";
|
|
55
55
|
};
|
|
56
|
+
readonly legal: {
|
|
57
|
+
readonly termsOfUse: "Terms of Use";
|
|
58
|
+
readonly conjunction: "and";
|
|
59
|
+
readonly privacyPolicy: "Privacy Policy";
|
|
60
|
+
};
|
|
56
61
|
readonly shareMessage: {
|
|
57
62
|
readonly wallart: "Preview wall art";
|
|
58
63
|
readonly rugs: "Preview rug";
|
|
@@ -161,6 +166,11 @@ declare const resources: {
|
|
|
161
166
|
readonly scanQrCode: "Отсканируйте этот QR-код камерой телефона, чтобы просмотреть объект в дополненной реальности";
|
|
162
167
|
readonly deviceRequirementsDisclaimer: "*Требуется устройство и браузер с поддержкой AR. Рекомендуем iOS 12 или новее с Safari либо Android 7.0 или новее с Chrome.";
|
|
163
168
|
};
|
|
169
|
+
readonly legal: {
|
|
170
|
+
readonly termsOfUse: "Условия использования";
|
|
171
|
+
readonly conjunction: "и";
|
|
172
|
+
readonly privacyPolicy: "Политика конфиденциальности";
|
|
173
|
+
};
|
|
164
174
|
readonly shareMessage: {
|
|
165
175
|
readonly wallart: "Примерить настенный декор";
|
|
166
176
|
readonly rugs: "Примерить ковер";
|
package/dist/index.js
CHANGED
|
@@ -21,9 +21,9 @@ import { formatHex, oklch } from "culori";
|
|
|
21
21
|
import qrcode from "qrcode";
|
|
22
22
|
import { GLTFExporter, USDZExporter } from "three/examples/jsm/Addons.js";
|
|
23
23
|
import "@google/model-viewer";
|
|
24
|
-
import { Clone, DragControls, Environment, useGLTF, useProgress } from "@react-three/drei";
|
|
24
|
+
import { Clone, DragControls, Environment, useGLTF, useProgress, useTexture } from "@react-three/drei";
|
|
25
25
|
import { Canvas, useLoader, useThree } from "@react-three/fiber";
|
|
26
|
-
import { ACESFilmicToneMapping, BufferGeometry, ClampToEdgeWrapping, DoubleSide, Float32BufferAttribute, LinearFilter, MathUtils, Matrix4, NearestFilter, PerspectiveCamera, Quaternion, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from "three";
|
|
26
|
+
import { ACESFilmicToneMapping, Box3, BufferGeometry, ClampToEdgeWrapping, DoubleSide, Float32BufferAttribute, LinearFilter, MathUtils, Matrix4, NearestFilter, PerspectiveCamera, Plane, Quaternion, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from "three";
|
|
27
27
|
import { Indicator as react_radio_group_Indicator, Item, Root as react_radio_group_Root } from "@radix-ui/react-radio-group";
|
|
28
28
|
import { Swiper, SwiperSlide } from "swiper/react";
|
|
29
29
|
var __webpack_modules__ = {
|
|
@@ -3029,6 +3029,14 @@ var __webpack_modules__ = {
|
|
|
3029
3029
|
font-variant-numeric: tabular-nums;
|
|
3030
3030
|
}
|
|
3031
3031
|
|
|
3032
|
+
.underline {
|
|
3033
|
+
text-decoration-line: underline;
|
|
3034
|
+
}
|
|
3035
|
+
|
|
3036
|
+
.underline-offset-2 {
|
|
3037
|
+
text-underline-offset: 2px;
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3032
3040
|
.underline-offset-4 {
|
|
3033
3041
|
text-underline-offset: 4px;
|
|
3034
3042
|
}
|
|
@@ -6595,6 +6603,11 @@ const ns1 = {
|
|
|
6595
6603
|
scanQrCode: 'Scan this QR code with your phone\'s camera to view the object in Augmented Reality',
|
|
6596
6604
|
deviceRequirementsDisclaimer: '*Requires AR-supported device and browser. We recommend iOS 12 or later with Safari, or Android 7.0 or later with Chrome.'
|
|
6597
6605
|
},
|
|
6606
|
+
legal: {
|
|
6607
|
+
termsOfUse: 'Terms of Use',
|
|
6608
|
+
conjunction: 'and',
|
|
6609
|
+
privacyPolicy: 'Privacy Policy'
|
|
6610
|
+
},
|
|
6598
6611
|
shareMessage: {
|
|
6599
6612
|
wallart: 'Preview wall art',
|
|
6600
6613
|
rugs: 'Preview rug',
|
|
@@ -6702,6 +6715,11 @@ const ns1_ns1 = {
|
|
|
6702
6715
|
scanQrCode: 'Отсканируйте этот QR-код камерой телефона, чтобы просмотреть объект в дополненной реальности',
|
|
6703
6716
|
deviceRequirementsDisclaimer: '*Требуется устройство и браузер с поддержкой AR. Рекомендуем iOS 12 или новее с Safari либо Android 7.0 или новее с Chrome.'
|
|
6704
6717
|
},
|
|
6718
|
+
legal: {
|
|
6719
|
+
termsOfUse: 'Условия использования',
|
|
6720
|
+
conjunction: 'и',
|
|
6721
|
+
privacyPolicy: 'Политика конфиденциальности'
|
|
6722
|
+
},
|
|
6705
6723
|
shareMessage: {
|
|
6706
6724
|
wallart: 'Примерить настенный декор',
|
|
6707
6725
|
rugs: 'Примерить ковер',
|
|
@@ -8697,12 +8715,16 @@ const config_env = {
|
|
|
8697
8715
|
NODE_API_BASE_URL: "https://api.neurodyn.ai/",
|
|
8698
8716
|
TENANTS: {
|
|
8699
8717
|
arizo: {
|
|
8718
|
+
PRIVACY_URL: 'https://arizo.ru/privacy-policy/',
|
|
8700
8719
|
POSTER_URL: "https://viewer.arizo.ru/poster/app/index.html",
|
|
8701
|
-
ROOM_URL: "https://
|
|
8720
|
+
ROOM_URL: "https://integrations.arizo.ru/room-viewer",
|
|
8721
|
+
TERMS_URL: 'https://arizo.ru/terms-of-use/'
|
|
8702
8722
|
},
|
|
8703
8723
|
vizbl: {
|
|
8724
|
+
PRIVACY_URL: 'https://vizbl.com/legal/privacy-policy',
|
|
8704
8725
|
POSTER_URL: "https://viewer.vizbl.com/poster/app/index.html",
|
|
8705
|
-
ROOM_URL: "https://integrations.vizbl.com/room-viewer"
|
|
8726
|
+
ROOM_URL: "https://integrations.vizbl.com/room-viewer",
|
|
8727
|
+
TERMS_URL: 'https://vizbl.com/legal/terms-of-use'
|
|
8706
8728
|
}
|
|
8707
8729
|
},
|
|
8708
8730
|
APP_CLIP_BUNDLE_ID: "com.us.vizbl.Clip"
|
|
@@ -9455,7 +9477,11 @@ function AR({ className, buttonClassName, buttonLeadingIcon, buttonLabel, button
|
|
|
9455
9477
|
const handleClick = async ()=>{
|
|
9456
9478
|
if ('floor' === placement) {
|
|
9457
9479
|
if (!tinuuid) return;
|
|
9458
|
-
if (isIOS && appClipUrl)
|
|
9480
|
+
if (isIOS && appClipUrl) {
|
|
9481
|
+
sendWidgetEvent(widgetSession, 'appclip');
|
|
9482
|
+
window.location.assign(appClipUrl);
|
|
9483
|
+
return;
|
|
9484
|
+
}
|
|
9459
9485
|
await refreshHandoffWidgetSessionToken();
|
|
9460
9486
|
setOpen(true);
|
|
9461
9487
|
return;
|
|
@@ -9542,9 +9568,37 @@ function AR({ className, buttonClassName, buttonLeadingIcon, buttonLabel, button
|
|
|
9542
9568
|
className: "text-lg text-center text-text-sub font-medium",
|
|
9543
9569
|
children: t('ar.scanQrCode')
|
|
9544
9570
|
}),
|
|
9545
|
-
/*#__PURE__*/
|
|
9571
|
+
/*#__PURE__*/ jsxs("p", {
|
|
9546
9572
|
className: "text-xs text-center text-text-light",
|
|
9547
|
-
children:
|
|
9573
|
+
children: [
|
|
9574
|
+
t('ar.deviceRequirementsDisclaimer'),
|
|
9575
|
+
/*#__PURE__*/ jsx_runtime_jsx("br", {}),
|
|
9576
|
+
/*#__PURE__*/ jsx_runtime_jsx("a", {
|
|
9577
|
+
href: tenantConfig.TERMS_URL,
|
|
9578
|
+
target: "_blank",
|
|
9579
|
+
rel: "noopener noreferrer",
|
|
9580
|
+
className: "underline underline-offset-2 transition-colors duration-300 hover:text-text-dark",
|
|
9581
|
+
style: {
|
|
9582
|
+
textDecoration: 'underline',
|
|
9583
|
+
textUnderlineOffset: '2px'
|
|
9584
|
+
},
|
|
9585
|
+
children: t('legal.termsOfUse')
|
|
9586
|
+
}),
|
|
9587
|
+
' ',
|
|
9588
|
+
t('legal.conjunction'),
|
|
9589
|
+
' ',
|
|
9590
|
+
/*#__PURE__*/ jsx_runtime_jsx("a", {
|
|
9591
|
+
href: tenantConfig.PRIVACY_URL,
|
|
9592
|
+
target: "_blank",
|
|
9593
|
+
rel: "noopener noreferrer",
|
|
9594
|
+
className: "underline underline-offset-2 transition-colors duration-300 hover:text-text-dark",
|
|
9595
|
+
style: {
|
|
9596
|
+
textDecoration: 'underline',
|
|
9597
|
+
textUnderlineOffset: '2px'
|
|
9598
|
+
},
|
|
9599
|
+
children: t('legal.privacyPolicy')
|
|
9600
|
+
})
|
|
9601
|
+
]
|
|
9548
9602
|
}),
|
|
9549
9603
|
/*#__PURE__*/ jsx_runtime_jsx(DialogClose, {
|
|
9550
9604
|
asChild: true,
|
|
@@ -9723,14 +9777,34 @@ async function canvasToPngBlob(canvas, errorMessage) {
|
|
|
9723
9777
|
}, 'image/png');
|
|
9724
9778
|
});
|
|
9725
9779
|
}
|
|
9780
|
+
function hideSceneCaptureExclusions(scene) {
|
|
9781
|
+
const previousVisibility = new Map();
|
|
9782
|
+
scene.traverse((object)=>{
|
|
9783
|
+
if (true === object.userData.excludeFromCapture) {
|
|
9784
|
+
previousVisibility.set(object, object.visible);
|
|
9785
|
+
object.visible = false;
|
|
9786
|
+
}
|
|
9787
|
+
});
|
|
9788
|
+
return ()=>{
|
|
9789
|
+
previousVisibility.forEach((visible, object)=>{
|
|
9790
|
+
object.visible = visible;
|
|
9791
|
+
});
|
|
9792
|
+
};
|
|
9793
|
+
}
|
|
9726
9794
|
function CanvasCaptureBridge({ ref }) {
|
|
9727
9795
|
const { camera, gl, invalidate, scene } = useThree();
|
|
9728
9796
|
useImperativeHandle(ref, ()=>({
|
|
9729
9797
|
capture: async ()=>{
|
|
9730
9798
|
invalidate();
|
|
9731
9799
|
await new Promise((resolve)=>requestAnimationFrame(()=>resolve()));
|
|
9732
|
-
|
|
9733
|
-
|
|
9800
|
+
const restoreVisibility = hideSceneCaptureExclusions(scene);
|
|
9801
|
+
try {
|
|
9802
|
+
gl.render(scene, camera);
|
|
9803
|
+
return await canvasToPngBlob(gl.domElement, 'Failed to create scene share image');
|
|
9804
|
+
} finally{
|
|
9805
|
+
restoreVisibility();
|
|
9806
|
+
invalidate();
|
|
9807
|
+
}
|
|
9734
9808
|
}
|
|
9735
9809
|
}), [
|
|
9736
9810
|
camera,
|
|
@@ -9766,6 +9840,17 @@ function createPoseFromPlane(mesh, point, camera, placement) {
|
|
|
9766
9840
|
activePlaneId: mesh.userData.planeId
|
|
9767
9841
|
};
|
|
9768
9842
|
}
|
|
9843
|
+
function createPointerDragOffset(resourcePose, pointerPose) {
|
|
9844
|
+
const inverseSurfaceQuaternion = new Quaternion(...pointerPose.quaternion).invert();
|
|
9845
|
+
return new Vector3(...resourcePose.position).sub(new Vector3(...pointerPose.position)).applyQuaternion(inverseSurfaceQuaternion).toArray();
|
|
9846
|
+
}
|
|
9847
|
+
function applyPointerDragOffset(pointerPose, offset) {
|
|
9848
|
+
const position = new Vector3(...offset).applyQuaternion(new Quaternion(...pointerPose.quaternion)).add(new Vector3(...pointerPose.position));
|
|
9849
|
+
return {
|
|
9850
|
+
...pointerPose,
|
|
9851
|
+
position: position.toArray()
|
|
9852
|
+
};
|
|
9853
|
+
}
|
|
9769
9854
|
function isRoomScenePlaneAllowedForResource(plane, placement) {
|
|
9770
9855
|
return 'floor' === placement ? 'floor' === plane.kind : 'floor' !== plane.kind;
|
|
9771
9856
|
}
|
|
@@ -9846,6 +9931,7 @@ function useRoomScenePlacement({ camera, invalidate, pointer, raycaster, roomId,
|
|
|
9846
9931
|
const [placementState, dispatchPlacementState] = useReducer(reduceRoomScenePlacementState, placementKey, createInitialRoomScenePlacementState);
|
|
9847
9932
|
const activePlaneIdRef = useRef(null);
|
|
9848
9933
|
const planeMapRef = useRef(new Map());
|
|
9934
|
+
const pointerDragOffsetRef = useRef(null);
|
|
9849
9935
|
const planeIdMap = placementState.placementKey === placementKey ? placementState.planeIdMap : null;
|
|
9850
9936
|
const resourcePose = placementState.placementKey === placementKey ? placementState.resourcePose : null;
|
|
9851
9937
|
const allowedPlanes = external_react_useMemo(()=>getAllowedRoomScenePlanes(scene, placement), [
|
|
@@ -9899,12 +9985,14 @@ function useRoomScenePlacement({ camera, invalidate, pointer, raycaster, roomId,
|
|
|
9899
9985
|
});
|
|
9900
9986
|
activePlaneIdRef.current = null;
|
|
9901
9987
|
activePlaneIdUniform.value = 0;
|
|
9988
|
+
pointerDragOffsetRef.current = null;
|
|
9902
9989
|
}, [
|
|
9903
9990
|
activePlaneIdUniform,
|
|
9904
9991
|
placementKey
|
|
9905
9992
|
]);
|
|
9906
|
-
const updatePoseFromPlane = useCallback((mesh, point)=>{
|
|
9907
|
-
const
|
|
9993
|
+
const updatePoseFromPlane = useCallback((mesh, point, pointerDragOffset = null)=>{
|
|
9994
|
+
const pointerPose = createPoseFromPlane(mesh, point, camera, placement);
|
|
9995
|
+
const pose = pointerDragOffset ? applyPointerDragOffset(pointerPose, pointerDragOffset) : pointerPose;
|
|
9908
9996
|
activePlaneIdRef.current = pose.activePlaneId;
|
|
9909
9997
|
activePlaneIdUniform.value = pose.activePlaneId;
|
|
9910
9998
|
dispatchPlacementState({
|
|
@@ -9964,17 +10052,37 @@ function useRoomScenePlacement({ camera, invalidate, pointer, raycaster, roomId,
|
|
|
9964
10052
|
resourcePose,
|
|
9965
10053
|
placement
|
|
9966
10054
|
]);
|
|
10055
|
+
const handleDragStart = useCallback(()=>{
|
|
10056
|
+
const hit = findHitForPointer(pointer);
|
|
10057
|
+
if (!hit || !resourcePose) {
|
|
10058
|
+
pointerDragOffsetRef.current = null;
|
|
10059
|
+
return;
|
|
10060
|
+
}
|
|
10061
|
+
const pointerPose = createPoseFromPlane(hit.object, hit.point, camera, placement);
|
|
10062
|
+
pointerDragOffsetRef.current = createPointerDragOffset(resourcePose, pointerPose);
|
|
10063
|
+
}, [
|
|
10064
|
+
camera,
|
|
10065
|
+
findHitForPointer,
|
|
10066
|
+
placement,
|
|
10067
|
+
pointer,
|
|
10068
|
+
resourcePose
|
|
10069
|
+
]);
|
|
9967
10070
|
const handleDrag = useCallback(()=>{
|
|
9968
10071
|
const hit = findHitForPointer(pointer);
|
|
9969
|
-
if (hit) updatePoseFromPlane(hit.object, hit.point);
|
|
10072
|
+
if (hit) updatePoseFromPlane(hit.object, hit.point, pointerDragOffsetRef.current);
|
|
9970
10073
|
}, [
|
|
9971
10074
|
findHitForPointer,
|
|
9972
10075
|
pointer,
|
|
9973
10076
|
updatePoseFromPlane
|
|
9974
10077
|
]);
|
|
10078
|
+
const handleDragEnd = useCallback(()=>{
|
|
10079
|
+
pointerDragOffsetRef.current = null;
|
|
10080
|
+
}, []);
|
|
9975
10081
|
return {
|
|
9976
10082
|
activePlaneIdUniform,
|
|
9977
10083
|
handleDrag,
|
|
10084
|
+
handleDragEnd,
|
|
10085
|
+
handleDragStart,
|
|
9978
10086
|
planeGeometries,
|
|
9979
10087
|
readiness,
|
|
9980
10088
|
resourcePose,
|
|
@@ -10091,16 +10199,128 @@ function collectClonedMaterials(source) {
|
|
|
10091
10199
|
});
|
|
10092
10200
|
return Array.from(materials);
|
|
10093
10201
|
}
|
|
10202
|
+
import arrows_rug_namespaceObject from "./static/image/arrows-rug.png";
|
|
10203
|
+
const CONTROL_SIZE_MULTIPLIER = 1.15;
|
|
10204
|
+
const CONTROL_SURFACE_GAP_MULTIPLIER = 0.001;
|
|
10205
|
+
function isRugRotationControlPrimaryHit(control, intersectedObjects) {
|
|
10206
|
+
return intersectedObjects[0] === control;
|
|
10207
|
+
}
|
|
10208
|
+
function createRugRotationControlLayout(resourceBounds) {
|
|
10209
|
+
const size = resourceBounds.getSize(new Vector3());
|
|
10210
|
+
const side = Math.max(size.x, size.y) * CONTROL_SIZE_MULTIPLIER;
|
|
10211
|
+
return {
|
|
10212
|
+
positionZ: resourceBounds.min.z - side * CONTROL_SURFACE_GAP_MULTIPLIER,
|
|
10213
|
+
side
|
|
10214
|
+
};
|
|
10215
|
+
}
|
|
10216
|
+
function normalizeDegrees(degrees) {
|
|
10217
|
+
return ((degrees + 180) % 360 + 360) % 360 - 180;
|
|
10218
|
+
}
|
|
10219
|
+
function getPointAngle(point, center, inverseSurfaceQuaternion) {
|
|
10220
|
+
const localPoint = point.clone().sub(center).applyQuaternion(inverseSurfaceQuaternion);
|
|
10221
|
+
return Math.atan2(localPoint.y, localPoint.x);
|
|
10222
|
+
}
|
|
10223
|
+
function resolveRugRotationDegrees({ center, currentPoint, initialPoint, initialRotation, surfaceQuaternion }) {
|
|
10224
|
+
const inverseSurfaceQuaternion = surfaceQuaternion.clone().invert();
|
|
10225
|
+
const initialAngle = getPointAngle(initialPoint, center, inverseSurfaceQuaternion);
|
|
10226
|
+
const currentAngle = getPointAngle(currentPoint, center, inverseSurfaceQuaternion);
|
|
10227
|
+
const deltaDegrees = MathUtils.radToDeg(currentAngle - initialAngle);
|
|
10228
|
+
return normalizeDegrees(initialRotation + deltaDegrees);
|
|
10229
|
+
}
|
|
10230
|
+
const CAPTURE_EXCLUSION_USER_DATA = {
|
|
10231
|
+
excludeFromCapture: true
|
|
10232
|
+
};
|
|
10233
|
+
function RugRotationControl({ resourceBounds }) {
|
|
10234
|
+
const { resourceRef, rotation, setIsDragging, setRotation } = useRoomViewerSceneState();
|
|
10235
|
+
const texture = useTexture(arrows_rug_namespaceObject);
|
|
10236
|
+
const gestureRef = useRef(null);
|
|
10237
|
+
const layout = external_react_useMemo(()=>createRugRotationControlLayout(resourceBounds), [
|
|
10238
|
+
resourceBounds
|
|
10239
|
+
]);
|
|
10240
|
+
useLayoutEffect(()=>{
|
|
10241
|
+
texture.colorSpace = SRGBColorSpace;
|
|
10242
|
+
texture.needsUpdate = true;
|
|
10243
|
+
}, [
|
|
10244
|
+
texture
|
|
10245
|
+
]);
|
|
10246
|
+
const handlePointerDown = (event)=>{
|
|
10247
|
+
const resource = resourceRef.current;
|
|
10248
|
+
if (!resource || !isRugRotationControlPrimaryHit(event.object, event.intersections.map((intersection)=>intersection.object))) return;
|
|
10249
|
+
event.stopPropagation();
|
|
10250
|
+
const pointerTarget = event.target;
|
|
10251
|
+
pointerTarget.setPointerCapture(event.pointerId);
|
|
10252
|
+
resource.updateWorldMatrix(true, false);
|
|
10253
|
+
const surfaceQuaternion = resource.getWorldQuaternion(new Quaternion());
|
|
10254
|
+
const center = resource.getWorldPosition(new Vector3());
|
|
10255
|
+
const normal = new Vector3(0, 0, 1).applyQuaternion(surfaceQuaternion);
|
|
10256
|
+
gestureRef.current = {
|
|
10257
|
+
center,
|
|
10258
|
+
initialPoint: event.point.clone(),
|
|
10259
|
+
initialRotation: rotation,
|
|
10260
|
+
plane: new Plane().setFromNormalAndCoplanarPoint(normal, center),
|
|
10261
|
+
pointerId: event.pointerId,
|
|
10262
|
+
pointerTarget,
|
|
10263
|
+
surfaceQuaternion
|
|
10264
|
+
};
|
|
10265
|
+
setIsDragging(true);
|
|
10266
|
+
};
|
|
10267
|
+
const handlePointerMove = (event)=>{
|
|
10268
|
+
const gesture = gestureRef.current;
|
|
10269
|
+
if (!gesture) return;
|
|
10270
|
+
event.stopPropagation();
|
|
10271
|
+
const currentPoint = event.ray.intersectPlane(gesture.plane, new Vector3());
|
|
10272
|
+
if (!currentPoint) return;
|
|
10273
|
+
setRotation(resolveRugRotationDegrees({
|
|
10274
|
+
...gesture,
|
|
10275
|
+
currentPoint
|
|
10276
|
+
}));
|
|
10277
|
+
};
|
|
10278
|
+
const endGesture = (event)=>{
|
|
10279
|
+
if (!gestureRef.current) return;
|
|
10280
|
+
event.stopPropagation();
|
|
10281
|
+
const { pointerId, pointerTarget } = gestureRef.current;
|
|
10282
|
+
if (pointerTarget.hasPointerCapture(pointerId)) pointerTarget.releasePointerCapture(pointerId);
|
|
10283
|
+
gestureRef.current = null;
|
|
10284
|
+
setIsDragging(false);
|
|
10285
|
+
};
|
|
10286
|
+
if (layout.side <= 0) return null;
|
|
10287
|
+
return /*#__PURE__*/ jsxs("mesh", {
|
|
10288
|
+
"position-z": layout.positionZ,
|
|
10289
|
+
userData: CAPTURE_EXCLUSION_USER_DATA,
|
|
10290
|
+
onPointerCancel: endGesture,
|
|
10291
|
+
onPointerDown: handlePointerDown,
|
|
10292
|
+
onPointerMove: handlePointerMove,
|
|
10293
|
+
onPointerUp: endGesture,
|
|
10294
|
+
children: [
|
|
10295
|
+
/*#__PURE__*/ jsx_runtime_jsx("planeGeometry", {
|
|
10296
|
+
args: [
|
|
10297
|
+
layout.side,
|
|
10298
|
+
layout.side
|
|
10299
|
+
]
|
|
10300
|
+
}),
|
|
10301
|
+
/*#__PURE__*/ jsx_runtime_jsx("meshBasicMaterial", {
|
|
10302
|
+
map: texture,
|
|
10303
|
+
transparent: true,
|
|
10304
|
+
depthWrite: false,
|
|
10305
|
+
side: DoubleSide,
|
|
10306
|
+
toneMapped: false
|
|
10307
|
+
})
|
|
10308
|
+
]
|
|
10309
|
+
});
|
|
10310
|
+
}
|
|
10094
10311
|
const FLOOR_RESOURCE_ROTATION_X = Math.PI / 2;
|
|
10095
10312
|
function FloorResource({ glbUrl, position, quaternion, materialPatch }) {
|
|
10313
|
+
const { type } = useRoomViewerMetadata();
|
|
10096
10314
|
const { resourceRef, rotation, setIsDragging } = useRoomViewerSceneState();
|
|
10097
10315
|
const gltf = useGLTF(glbUrl);
|
|
10098
|
-
const { sceneInstance, materials } = external_react_useMemo(()=>{
|
|
10316
|
+
const { sceneInstance, materials, resourceBounds } = external_react_useMemo(()=>{
|
|
10099
10317
|
const sceneInstance = gltf.scene.clone(true);
|
|
10100
10318
|
const materials = collectClonedMaterials(sceneInstance);
|
|
10319
|
+
const resourceBounds = new Box3().setFromObject(sceneInstance).applyMatrix4(new Matrix4().makeRotationX(FLOOR_RESOURCE_ROTATION_X));
|
|
10101
10320
|
return {
|
|
10102
10321
|
sceneInstance,
|
|
10103
|
-
materials
|
|
10322
|
+
materials,
|
|
10323
|
+
resourceBounds
|
|
10104
10324
|
};
|
|
10105
10325
|
}, [
|
|
10106
10326
|
gltf
|
|
@@ -10124,14 +10344,19 @@ function FloorResource({ glbUrl, position, quaternion, materialPatch }) {
|
|
|
10124
10344
|
onPointerDown: ()=>setIsDragging(true),
|
|
10125
10345
|
onPointerUp: ()=>setIsDragging(false),
|
|
10126
10346
|
onPointerLeave: ()=>setIsDragging(false),
|
|
10127
|
-
children: /*#__PURE__*/
|
|
10347
|
+
children: /*#__PURE__*/ jsxs("group", {
|
|
10128
10348
|
"rotation-z": rotationRadians,
|
|
10129
|
-
children:
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10349
|
+
children: [
|
|
10350
|
+
'rugs' === type ? /*#__PURE__*/ jsx_runtime_jsx(RugRotationControl, {
|
|
10351
|
+
resourceBounds: resourceBounds
|
|
10352
|
+
}) : null,
|
|
10353
|
+
/*#__PURE__*/ jsx_runtime_jsx("group", {
|
|
10354
|
+
"rotation-x": FLOOR_RESOURCE_ROTATION_X,
|
|
10355
|
+
children: /*#__PURE__*/ jsx_runtime_jsx("primitive", {
|
|
10356
|
+
object: sceneInstance
|
|
10357
|
+
})
|
|
10133
10358
|
})
|
|
10134
|
-
|
|
10359
|
+
]
|
|
10135
10360
|
})
|
|
10136
10361
|
});
|
|
10137
10362
|
}
|
|
@@ -10602,6 +10827,8 @@ function Room() {
|
|
|
10602
10827
|
'floor' === placement ? scenePlacement.resourcePose && glbUrl && /*#__PURE__*/ jsx_runtime_jsx(DragControls, {
|
|
10603
10828
|
autoTransform: false,
|
|
10604
10829
|
onDrag: scenePlacement.handleDrag,
|
|
10830
|
+
onDragEnd: scenePlacement.handleDragEnd,
|
|
10831
|
+
onDragStart: scenePlacement.handleDragStart,
|
|
10605
10832
|
children: /*#__PURE__*/ jsx_runtime_jsx(FloorResource, {
|
|
10606
10833
|
glbUrl: glbUrl,
|
|
10607
10834
|
position: scenePlacement.resourcePose.position,
|
|
@@ -10611,6 +10838,8 @@ function Room() {
|
|
|
10611
10838
|
}) : scenePlacement.resourcePose && src && /*#__PURE__*/ jsx_runtime_jsx(DragControls, {
|
|
10612
10839
|
autoTransform: false,
|
|
10613
10840
|
onDrag: scenePlacement.handleDrag,
|
|
10841
|
+
onDragEnd: scenePlacement.handleDragEnd,
|
|
10842
|
+
onDragStart: scenePlacement.handleDragStart,
|
|
10614
10843
|
children: /*#__PURE__*/ jsx_runtime_jsx(WallResource, {
|
|
10615
10844
|
src: src,
|
|
10616
10845
|
position: scenePlacement.resourcePose.position,
|
|
Binary file
|