@terraware/web-components 4.2.19 → 4.2.20-rc.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SplatControls.d.ts","sourceRoot":"","sources":["../../../src/components/VirtualWalkthrough/SplatControls.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SplatControls.d.ts","sourceRoot":"","sources":["../../../src/components/VirtualWalkthrough/SplatControls.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAA2B,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAyB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE/E,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,uBAAuB,CAAC;IAC1C,UAAU,EAAE,iBAAiB,CAAC;IAC9B,kBAAkB,EAAE,yBAAyB,CAAC;CAC/C;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,qBAAqB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,kBAAkB,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC5C,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IAChE,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,QAAA,MAAM,aAAa,GAAI,2dA8BpB,kBAAkB,4CAwKpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useRef
|
|
1
|
+
import React, { useCallback, useEffect, useRef } from 'react';
|
|
2
2
|
import { Fullscreen, FullscreenExit } from '@mui/icons-material';
|
|
3
3
|
import { Box, IconButton, useTheme } from '@mui/material';
|
|
4
|
-
import { useApp } from '@playcanvas/react/hooks';
|
|
5
|
-
import { XRSPACE_LOCAL, XRTYPE_AR, XRTYPE_VR } from 'playcanvas';
|
|
6
4
|
import useBoolean from '../../hooks/useBoolean';
|
|
7
5
|
import { useCameraPosition } from '../../hooks/useCameraPosition';
|
|
6
|
+
import { useXr } from '../../hooks/useXr';
|
|
8
7
|
import { getRgbaFromHex } from '../../utils/color';
|
|
9
8
|
import useDeviceInfo from '../../utils/useDeviceInfo';
|
|
10
9
|
import Button from '../Button/Button';
|
|
@@ -48,51 +47,19 @@ const SplatControls = ({
|
|
|
48
47
|
const {
|
|
49
48
|
isDesktop
|
|
50
49
|
} = useDeviceInfo();
|
|
51
|
-
const app = useApp();
|
|
52
50
|
const {
|
|
53
51
|
setCamera,
|
|
54
52
|
getCameraState
|
|
55
53
|
} = useCameraPosition();
|
|
56
|
-
const
|
|
57
|
-
|
|
54
|
+
const {
|
|
55
|
+
isXrAvailable,
|
|
56
|
+
startXr
|
|
57
|
+
} = useXr({
|
|
58
|
+
onError
|
|
59
|
+
});
|
|
58
60
|
const [isInfoVisible, setIsInfoVisible] = useBoolean(true);
|
|
59
61
|
const paneRef = useRef(null);
|
|
60
62
|
const infoButtonRef = useRef(null);
|
|
61
|
-
const errorCallback = useCallback(err => {
|
|
62
|
-
if (err) {
|
|
63
|
-
onError?.(err);
|
|
64
|
-
app.xr?.end();
|
|
65
|
-
}
|
|
66
|
-
}, [app, onError]);
|
|
67
|
-
const handleAr = useCallback(() => app.xr?.start(app.root.findComponent('camera'), XRTYPE_AR, XRSPACE_LOCAL, {
|
|
68
|
-
callback: errorCallback
|
|
69
|
-
}), [app, errorCallback]);
|
|
70
|
-
const handleVr = useCallback(() => app.xr?.start(app.root.findComponent('camera'), XRTYPE_VR, XRSPACE_LOCAL, {
|
|
71
|
-
callback: errorCallback
|
|
72
|
-
}), [app, errorCallback]);
|
|
73
|
-
useEffect(() => {
|
|
74
|
-
// this can't be changed to `useMemo(() => app.xr?.isAvailable(XRTYPE_AR), [app])` because `app` doesn't update when
|
|
75
|
-
// XR's availability is updated
|
|
76
|
-
const handleAvailable = (type, available) => {
|
|
77
|
-
if (type === XRTYPE_VR) {
|
|
78
|
-
setIsVrAvailable(available);
|
|
79
|
-
} else if (type === XRTYPE_AR) {
|
|
80
|
-
setIsArAvailable(available);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// Check current availability state on mount
|
|
85
|
-
if (app.xr?.isAvailable(XRTYPE_VR)) {
|
|
86
|
-
setIsVrAvailable(true);
|
|
87
|
-
}
|
|
88
|
-
if (app.xr?.isAvailable(XRTYPE_AR)) {
|
|
89
|
-
setIsArAvailable(true);
|
|
90
|
-
}
|
|
91
|
-
app.xr?.on('available', handleAvailable);
|
|
92
|
-
return () => {
|
|
93
|
-
app.xr?.off('available', handleAvailable);
|
|
94
|
-
};
|
|
95
|
-
}, [app]);
|
|
96
63
|
useEffect(() => {
|
|
97
64
|
const handleKeyPress = event => {
|
|
98
65
|
if (event.key === 'r' || event.key === 'R') {
|
|
@@ -171,12 +138,12 @@ const SplatControls = ({
|
|
|
171
138
|
gap: 1,
|
|
172
139
|
pointerEvents: 'auto'
|
|
173
140
|
},
|
|
174
|
-
children: [
|
|
141
|
+
children: [isXrAvailable('AR') && !isEdit && /*#__PURE__*/_jsx(Button, {
|
|
175
142
|
label: strings.ar,
|
|
176
|
-
onClick:
|
|
177
|
-
}),
|
|
143
|
+
onClick: () => startXr('AR')
|
|
144
|
+
}), isXrAvailable('VR') && !isEdit && /*#__PURE__*/_jsx(Button, {
|
|
178
145
|
label: strings.vr,
|
|
179
|
-
onClick:
|
|
146
|
+
onClick: () => startXr('VR')
|
|
180
147
|
}), isDesktop && editable && !isEdit && onToggleEdit && /*#__PURE__*/_jsx(Button, {
|
|
181
148
|
label: strings.edit,
|
|
182
149
|
onClick: handleEdit
|
package/hooks/useXr.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type XrType = 'VR' | 'AR';
|
|
2
|
+
interface UseXrOptions {
|
|
3
|
+
onError?: (error: Error) => void;
|
|
4
|
+
}
|
|
5
|
+
export declare const useXr: ({ onError }?: UseXrOptions) => {
|
|
6
|
+
isXrAvailable: (type: XrType) => boolean;
|
|
7
|
+
startXr: (type: XrType) => void;
|
|
8
|
+
endXr: () => void;
|
|
9
|
+
isCurrentlyInXr: boolean;
|
|
10
|
+
};
|
|
11
|
+
export default useXr;
|
|
12
|
+
//# sourceMappingURL=useXr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useXr.d.ts","sourceRoot":"","sources":["../../src/hooks/useXr.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjC,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAOD,eAAO,MAAM,KAAK,GAAI,cAAa,YAAiB;0BA0CT,MAAM;oBAGtC,MAAM;;;CAsBhB,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
package/hooks/useXr.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { useApp } from '@playcanvas/react/hooks';
|
|
3
|
+
import { XRSPACE_LOCALFLOOR, XRTYPE_AR, XRTYPE_VR } from 'playcanvas';
|
|
4
|
+
const XR_TYPES = {
|
|
5
|
+
VR: XRTYPE_VR,
|
|
6
|
+
AR: XRTYPE_AR
|
|
7
|
+
};
|
|
8
|
+
export const useXr = ({
|
|
9
|
+
onError
|
|
10
|
+
} = {}) => {
|
|
11
|
+
const app = useApp();
|
|
12
|
+
const [available, setAvailable] = useState({
|
|
13
|
+
VR: false,
|
|
14
|
+
AR: false
|
|
15
|
+
});
|
|
16
|
+
const [isCurrentlyInXr, setIsCurrentlyInXr] = useState(app.xr?.active ?? false);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
// We subscribe to the manager directly because `app` doesn't update when XR's availability changes.
|
|
19
|
+
const handleAvailable = (type, isAvailable) => {
|
|
20
|
+
if (type === XRTYPE_VR) {
|
|
21
|
+
setAvailable(prev => ({
|
|
22
|
+
...prev,
|
|
23
|
+
VR: isAvailable
|
|
24
|
+
}));
|
|
25
|
+
} else if (type === XRTYPE_AR) {
|
|
26
|
+
setAvailable(prev => ({
|
|
27
|
+
...prev,
|
|
28
|
+
AR: isAvailable
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
setAvailable({
|
|
33
|
+
VR: app.xr?.isAvailable(XRTYPE_VR) ?? false,
|
|
34
|
+
AR: app.xr?.isAvailable(XRTYPE_AR) ?? false
|
|
35
|
+
});
|
|
36
|
+
app.xr?.on('available', handleAvailable);
|
|
37
|
+
return () => {
|
|
38
|
+
app.xr?.off('available', handleAvailable);
|
|
39
|
+
};
|
|
40
|
+
}, [app]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const handleStart = () => setIsCurrentlyInXr(true);
|
|
43
|
+
const handleEnd = () => setIsCurrentlyInXr(false);
|
|
44
|
+
setIsCurrentlyInXr(app.xr?.active ?? false);
|
|
45
|
+
app.xr?.on('start', handleStart);
|
|
46
|
+
app.xr?.on('end', handleEnd);
|
|
47
|
+
return () => {
|
|
48
|
+
app.xr?.off('start', handleStart);
|
|
49
|
+
app.xr?.off('end', handleEnd);
|
|
50
|
+
};
|
|
51
|
+
}, [app]);
|
|
52
|
+
const isXrAvailable = useCallback(type => available[type], [available]);
|
|
53
|
+
const startXr = useCallback(type => {
|
|
54
|
+
const camera = app.root.findComponent('camera');
|
|
55
|
+
app.xr?.start(camera, XR_TYPES[type], XRSPACE_LOCALFLOOR, {
|
|
56
|
+
callback: err => {
|
|
57
|
+
if (err) {
|
|
58
|
+
onError?.(err);
|
|
59
|
+
app.xr?.end();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}, [app, onError]);
|
|
64
|
+
const endXr = useCallback(() => {
|
|
65
|
+
app.xr?.end();
|
|
66
|
+
}, [app]);
|
|
67
|
+
return useMemo(() => ({
|
|
68
|
+
isXrAvailable,
|
|
69
|
+
startXr,
|
|
70
|
+
endXr,
|
|
71
|
+
isCurrentlyInXr
|
|
72
|
+
}), [isXrAvailable, startXr, endXr, isCurrentlyInXr]);
|
|
73
|
+
};
|
|
74
|
+
export default useXr;
|